Skip to main content
Version: v0.0.7

Interface: X12OrphanSegment

A segment the envelope grammar has no place for, captured verbatim rather than discarded. Every segment recorded here also raised exactly one X12_UNEXPECTED_SEGMENT warning whose position.segmentIndex equals segmentIndex, and context is that warning's library-owned discriminant, so the two surfaces can be joined without string matching.

These are structural anomalies, not a normal shape: a stray segment between GE and IEA, a body segment between an SE and its group's GE, a body segment between GS and the first ST, an ST with no open group, an SE closing nothing, a GE closing nothing, or a TA1 inside an open functional group. The parser cannot place any of them in the typed tree, but it no longer drops them either, so a segment that used to vanish is now readable here.

Most of these sit outside every ST..SE transaction set, but the TA1 case does not. TA1 is envelope-level by spec, so a TA1 anywhere inside an open group is routed here even when it arrives BETWEEN an ST and its SE - in which case it is lifted out of that transaction's segments / rawSegments and appears only on this array. That is long-standing behaviour (it predates this array; the segment simply used to be discarded), and it is the one case where ix.groups is not the whole typed model.

serializeX12 re-emits these, at anchor, so an orphan and its X12_UNEXPECTED_SEGMENT warning both survive a round trip. Placement is by the structural anchor and NEVER by segmentIndex: that index is an index into the INPUT stream, and the emit is not in input order (it hoists ta1Segments ahead of the groups and skips the zero-length segment a doubled terminator produces), so replaying by index splices an orphan into whatever occupies that slot - measurably, into an 835's ST..SE body, where a re-parse reports nothing at all. Use segmentIndex to join back to the warning, not to place the segment. See KNOWN-LIMITATIONS.md.

Two things are NOT recorded here. A doubled segment terminator delimits a zero-length segment carrying no elements, so there is nothing to retain. A segment whose first element is empty (*A*B~) has no id for the envelope walker to dispatch on and is skipped without a warning; that is long-standing behaviour this array does not change.

This is document content, so treat it as PHI. Unlike an X12ParseWarning, whose message is a lookup into a frozen registry and whose metadata is positional only, an orphan carries the sender's bytes verbatim, exactly as X12TransactionSet.rawSegments and isa.raw do. A segment outside a transaction is not required to be PHI-free, so do NOT log this array wholesale when triaging; log context and segmentIndex, which name the structural rule and the location without echoing content.

Example

import { parseX12 } from "@cosyte/x12";
const ix = parseX12(raw);
for (const o of ix.orphanSegments) {
console.warn(o.context, o.segmentIndex, o.segment.id);
}

Properties

anchor

readonly anchor: X12OrphanAnchor

Where the segment sat in the typed tree - the slot serializeX12 puts it back into. See X12OrphanAnchor for why a structural anchor and not segmentIndex is what makes re-emission sound.


context

readonly context: X12UnexpectedSegmentContext

Which structural rule the segment broke.


raw

readonly raw: string

The verbatim segment text, segment terminator stripped.


segment

readonly segment: X12Segment

The decoded segment (id + 1-indexed elements), as for any body segment.


segmentIndex

readonly segmentIndex: number

Global segment index in the post-ISA stream (ISA itself is index 0) - identical to the position.segmentIndex of the segment's X12_UNEXPECTED_SEGMENT warning.