HSN sits next to the description on a purchase line. On a clean PDF it is eight digits and boring. On a photocopy OCR reads 72142 (five digits, illegal) or 7214.20.00 with dots, or drops a zero and leaves seven digits. The rupees can still add. The return still cares about the code.
This page is the check, not a rate list. For headings you often see on factory paper, see HSN codes on manufacturing invoices. Rates live on CBIC’s goods and services rate page and the GST HSN/SAC search. If those two disagree with a table in a blog, the blog is wrong.
Format: is this even an HSN-shaped string? Directory: does this string exist in a CBIC-derived snapshot (or as a prefix of one)? Format is the gate today. Directory is shadow by default so a laggy snapshot does not kill straight-through on real invoices.
Format: digits, and only 2, 4, 6 or 8 of them
Indian invoices print HSN without dots more often than with them. The Harmonized System tree uses dots in textbooks (7214.20). The voucher should store 72142000. EntryLedger strips non-digits first, so 0801.10.00 becomes 08011000 before the test.
After that, length must be 2, 4, 6 or 8. Two-digit chapter codes show up on some B2C paper. Four, six and eight are the usual B2B lengths. GST rules on which length you must file depend on turnover and current notifications. Look that up on the GST portal. Do not memorise a slab from 2019 and file it in 2026.
Five digits fail. Seven digits fail. Letters fail. A blank on a line is not a format failure in the orchestrator today: format runs only when the line already has an HSN. That is a product fact, not a boast. If you need “every purchase line must carry HSN,” tell us and we will scope it. We should not pretend the current gate invents a code the scan never showed.
72142 length 5 → fail
7214200 length 7 → fail
72142000 8 digits → pass format
Known or prefix of a listed code → ok
Miss + shadow → warning only
Miss + live → NEEDS_REVIEW
Dataset absent: directory fails open. Format still ran. That is deliberate. A missing file must not invent a block.
Directory: a snapshot, not live GSTN
Full tariff lookup is thousands of codes. We ship a sorted list (validators/data/hsn_codes.txt, 16,825 unique codes in the current bundle) compiled from a public CBIC-derived dataset, MIT-licensed. Provenance and fetch date are in the data manifest next to the file. It is not a GSTN API. It will lag notifications. Anyone who tells you their Excel is “the” HSN directory forever is selling you a freeze-frame.
Membership is prefix-aware. Invoices print heading-level codes whose tariff rows live at 8 digits. 1101 matches because 11010000 is in the list. That is why a 4-digit printout should not fail directory just for being short.
Known gap, from our own fixtures: 72142000 (older tariff wording for certain bars) is split in this snapshot into 72142010 / 72142090. The paper still says 72142000. If directory were live on day one, that legitimate line would go to review. That is why default is HSN_DIRECTORY=shadow: record a warning, leave routing alone. live turns the miss into a gate failure. Turn live on after a shadow run on your corpus shows an acceptable miss rate. Same philosophy as the rest of the ladder: do not burn straight-through to look strict on a stale list.
SAC (services) is a different series. A freight line with an HSN heading, or a steel line with a SAC, is classification, not format. Format will not save you. A person who knows the goods still has to look. We do not auto-rewrite HSN to “the rate you remember.”
What EntryLedger actually does per line
validate_invoice walks lines. If hsn_code is set, it runs format. Failures append line[i] HSN invalid: … and the invoice cannot auto-export. If format passes and directory mode is not off, it asks directory_known. Miss in shadow: warning on the audit trail. Miss in live: same string as a failure. The review UI should show which line and which code. A CA asking “why did this not export?” should get that string, not a shrug.
HSN is not GSTIN. A bad GSTIN checksum is almost always a typo. A well-formed HSN can still be the wrong product. Directory existence is not “this is the right heading for TMT bar vs merchant bar.” It is “this token appears in the snapshot.” Do not sell it as classification AI.
Arithmetic still has to close. A line with a pretty HSN and a tax that does not match rate × taxable still fails the math gate. HSN validation does not replace closure. Filing still cares about both the code and the rupees.
| What you see on paper | Format | Directory (shadow) | Auto-export? |
|---|---|---|---|
72142 (OCR drop) | Fail | not run | No |
7214.20.00 → stripped 8 digits | Pass if 8 digits | Warn if snapshot split | Yes, unless other gates fail |
72142010 in snapshot | Pass | Known | If math and GSTIN pass |
| Line with no HSN | Not run | Not run | Possible today |
| Well-formed code, wrong goods | Pass | Maybe known | Yes. Human job. |
What to do before GSTR, without waiting for software
Search the code on the GST HSN/SAC tool. Confirm the description is the goods you bought. Confirm the rate on the current CBIC notification, not last year’s printout on the cabin wall. If the supplier filed a different heading, that is a 2B conversation, not an OCR conversation. 2B mismatches have more than one parent.
Digit length for your returns follows GST rules for your turnover. We will not paste a crore threshold here. Thresholds move. The portal is the source.
If you key by hand, forbid 5-digit and 7-digit paste. If you capture by scan, run format before Tally. If you want directory as a hard gate, run shadow for a month, read the warning log, then flip live. That order is how you avoid blocking 72142000 because a snapshot split it.
ITC delay from a wrong or missing HSN is a filing and scrutiny risk, not a formula we can quote as rupees. Section 16 still needs a valid tax invoice and the other statutory conditions. Read the CGST Act. A blog is not a notification.
SAC on the same invoice
A factory purchase often mixes goods and a service: steel plus freight, a machine plus installation. Goods use HSN. Services use SAC. Format still applies (digit shape). Directory membership for SAC is not the same list as goods HSN. Do not force a freight line into chapter 72 because “everything on this PO is steel.” The CA will see it at filing even if the rate looks familiar.
OCR mixes these up when the scan has one tax table and two kinds of lines. The review reason should name the line index. The clerk’s job is then: is this row a good or a service? Pick the series the law wants. We will not silently rewrite it.
E-invoice, where mandated, also carries HSN/SAC on the IRN payload. That is a GSTN fact, not our feature. If the photocopy disagrees with an IRN the supplier already generated, believe GSTN for that document and stop capturing pixels. HSN validation on a scan is for paper that never got an IRN, or whose QR did not survive the copier.
How this shows up in a bake-off
Ask the vendor: “On a line where OCR emitted five digits, do you export?” If yes, they do not have format. Ask: “If the code is eight digits but absent from your list, do you block or warn?” If they cannot say, they have not thought about snapshot lag. Ask: “Can I see the line index and the reason on the audit trail?” If the answer is a confidence score, that is not HSN validation.
EntryLedger’s answers, as shipped: five digits fail format and cannot auto-export. Directory miss warns in shadow, blocks in live. Audit trail stores failures and warnings. Last updated with this post: 27 May 2026. Code: app/entryledger/validators/hsn.py and the orchestrator loop on lines.
- CBICcbic-gst.gov.in: GST rates by HSN
Official rate list. Use this, not a blog table.
- GST portalservices.gst.gov.in: HSN/SAC search
Look up a code and its description.
- CBICcbic-gst.gov.in
Acts, circulars, notifications. Digit-length rules live in GST law and later notices, not here.
- EntryLedger/validation
Gate docs. HSN format always; directory shadow default, live opt-in.
How many digits is an HSN?+
On paper: 2, 4, 6 or 8. What you must file depends on GST rules for your turnover. Check the portal.
Will a missing HSN stop export?+
Not by itself in the current orchestrator. Format runs when a line already has a code. Ask for a required-HSN rule if you need it.
Is directory live GSTN?+
No. It is a bundled snapshot with prefix match. It lags. That is why live is opt-in.
Where do I confirm the rate?+
CBIC rate page and GST HSN search. Never from this article.