The blog  ·  2026-07-31

The ISA segment is 106 characters of load-bearing whitespace

Written for ED-1 — the supply-chain ISV / traceability-vendor engineering org — the integration engineer whose partner file "won't parse".

One thesis: the ISA segment is positional — 106 characters, fixed-width, where the padding is part of the data — and once you parse it correctly, most of what gets called "EDI is hard" turns out to have been envelope trouble all along. The document grammars have their complexities, but the files that fail in production overwhelmingly fail before the first ST.

Why fixed-width, in a delimited format

The history takes three sentences. X12 descends from formats designed for machines that read records by byte offset, and the interchange header kept that discipline so a receiver could read the envelope before knowing the delimiters — because the envelope is where the delimiters are declared. Everything after the ISA is delimited; the ISA itself cannot be, not fully, because it bootstraps the delimiters. So its sixteen elements have fixed widths, short values are padded with spaces to width, and the total comes to exactly 106 characters including the terminator.

That is the whole trick, and it is also the whole trap: whitespace that looks cosmetic is load-bearing, and an ISA of 104 or 107 characters is not "close" — it is a different, wrong file.

The byte ruler

A synthetic, license-clean interchange header, with positions annotated (1-indexed; this description of positional layout is fact, in our own words — element-by-element dictionary detail belongs to the licensed X12 reference at Stedi, which we link and never republish):

ISA*00*          *00*          *ZZ*SELLERID       *ZZ*BUYERID        *260731*0915*U*00401*000000101*0*P*>~

bytes 1–3     "ISA"
byte  4       the element separator — declared by use; here "*"
bytes 5–6     authorization qualifier   (2, "00" = none)
bytes 8–17    authorization information (10, all spaces here — significant)
bytes 19–20   security qualifier        (2)
bytes 22–31   security information      (10, spaces again)
bytes 33–34   sender ID qualifier       (2, "ZZ" = mutually defined)
bytes 36–50   sender ID                 (15, "SELLERID" + 7 pad spaces)
bytes 52–53   receiver ID qualifier     (2)
bytes 55–69   receiver ID               (15, "BUYERID" + 8 pad spaces)
bytes 71–76   date                      (6, YYMMDD)
bytes 78–81   time                      (4, HHMM)
byte  83      repetition separator in 005010+; standards ID "U" in 004010
bytes 85–89   version                   (5, "00401")
bytes 91–99   interchange control number (9, zero-padded)
byte  101     acknowledgment requested  (1)
byte  103     usage                     (1, "P" production / "T" test)
byte  105     the component (sub-element) separator — here ">"
byte  106     the segment terminator — here "~"; everything after ISA obeys it

Three of those positions are not data at all but declarations: byte 4 teaches the receiver the element separator, byte 105 the component separator, byte 106 the segment terminator. The envelope describes its own syntax — the full consequences of that are the delimiter post.

The five envelope failures we see most

The fuzz corpus generates envelope pathologies by the hundred thousand; production files keep reproducing the same five. Each produces a typed error from parse — a machine-readable code with a position, on stderr, never a shrug:

  • Short or long ISA. A sender's system trimmed trailing spaces from ISA06 or ISA08 — the file is now 104 characters to the first terminator and every subsequent offset is wrong. Typed as an envelope-length error with the observed length; the fix is the sender's padding, not your parser's tolerance.
  • Wrong padding character. Zero-padded alphanumeric IDs or, worse, tab-padded ones — visually identical in most editors, byte-distinct on the wire. The error cites the offending byte and offset.
  • CRLF drift. The terminator is ~ but the file was FTP'd in text mode and every segment now ends ~\r\n — or the terminator is the newline and a transfer normalized CRLF to LF, silently editing the data. Typed as a terminator-consistency error; the parse does not guess which convention was meant.
  • Eight-bit characters. A partner's name field carries a byte outside the basic character set — fine in some receivers, fatal in others. Flagged with position and byte value, because "works with our other partners" is not a parse verdict.
  • Terminator collision. The declared component separator or terminator also appears inside data — legal-looking, structurally ruinous, and the reason a correct parser trusts the declarations and only the declarations rather than sniffing for "likely" delimiters.

Whether the counts and control numbers inside a structurally sound envelope agree with themselves is the next layer of failure, and it has its own post: the control-number handshake.

The honest claim

Parse the envelope right — fixed-width ISA, declared delimiters, typed rejections with byte positions — and roughly half of the folk reputation of EDI evaporates. Not the interesting half: the document grammars, the partner-guide variation, and the semantics of compiling documents onto event records (which is this site's actual subject — start at the 856 compile, and see what a conformant record buys at epcis.dev) all remain. But the 2 a.m. page about a partner file that "won't parse" is, in our corpus, an envelope story far more often than a grammar story — and envelope stories end fast when the error names its byte.

parse is the first verb in the pipeline and the one every other verb stands on: bytes in, lossless canonical JSON out, typed error with a position when the envelope lies. If your partner files have a folder of known horrors, that folder is exactly what the access flow wants to hear about — the fuzz corpus grew out of files like yours.


892 words. The access flow is at /get-access/; the family's event door is epcis.dev.