{"record":{"id":"e4369c4454568f92","repo":"docling-project/docling","slug":"no-record-layout-matches-record-type-record-type","errorCode":null,"errorMessage":"No record layout matches record type {record_type!r}.","messagePattern":"No record layout matches record type (.+?)\\.","errorType":"exception","errorClass":"EbcdicDecodeError","httpStatus":null,"severity":"error","filePath":"docling/backend/ebcdic_backend.py","lineNumber":167,"sourceCode":"        self, data: bytes, offset: int, end: int\n    ) -> tuple[EbcdicRecordLayout, int, int]:\n        \"\"\"Consume the record prefix and resolve the schema and body size.\"\"\"\n        layout = self._layout\n        length: Union[int, None] = None\n        record_type: Union[str, None] = None\n\n        if (field := layout.record_length_field) is not None:\n            chunk = self._take(data, offset, field.size, end, field.name)\n            length = int(self._decoder.decode(chunk, field))\n            offset += field.size\n        if (field := layout.record_type_field) is not None:\n            chunk = self._take(data, offset, field.size, end, field.name)\n            record_type = str(self._decoder.decode(chunk, field))\n            offset += field.size\n\n        record = layout.select(record_type)\n        if record is None:\n            raise EbcdicDecodeError(\n                f\"No record layout matches record type {record_type!r}.\"\n            )\n\n        size = record.size if length is None else length - layout.prefix_size\n        if size < 0:\n            raise EbcdicDecodeError(\n                f\"Record length {length} is shorter than the \"\n                f\"{layout.prefix_size}-byte record prefix.\"\n            )\n        return record, size, offset\n\n    @staticmethod\n    def _take(data: bytes, offset: int, size: int, end: int, name: str) -> bytes:\n        if offset + size > end:\n            raise EbcdicDecodeError(\n                f\"Input ends inside {name!r}: {end - offset} of {size} bytes left.\"\n            )\n        return data[offset : offset + size]","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/ebcdic_backend.py#L149-L185","documentation":"EbcdicDecodeError raised during record framing: the backend decoded the record-type prefix field and called layout.select(record_type), but no EbcdicRecordLayout in the layout declares that type value, so it cannot know how to parse the record body. The message shows the decoded record_type value — comparing it with your layout's declared record types is the whole debugging step.","triggerScenarios":"Data contains a record type token not declared in layout.records (new record variant, regional record, or versioned format); the record_type_field is mis-declared (wrong size/offset/type/encoding) so a valid type decodes to garbage; records where the type field overlaps other data because offsets shifted.","commonSituations":"Layout built from an old copybook while the feed added new record types; record_type declared as STRING but stored as zoned/packed numeric (or vice versa); fixed-vs-variable length prefix confusion causing the type bytes to be read from the wrong position.","solutions":["Compare the record_type value in the message with the type values declared on your records — add a matching EbcdicRecordLayout (or extend its type list) if the data legitimately contains that variant.","If the value looks like mojibake, fix record_type_field: correct size, offsets, and encoding (e.g. decode via zoned decimal if the field is numeric).","Confirm record_length_field handling: a wrong length shifts the offset at which the type is read.","Print the raw prefix bytes around the failing record and reconcile them against the copybook."],"exampleFix":"# before\nlayout = EbcdicLayout(\n    records=[EbcdicRecordLayout(name='detail', record_types={'D'})],\n    record_type_field=EbcdicField(name='RT', type=EbcdicFieldType.STRING, size=1),\n)\n# data contains 'H' header records -> No record layout matches record type 'H'\n\n# after\nrecords=[\n    EbcdicRecordLayout(name='header', record_types={'H'}, fields=[...]),\n    EbcdicRecordLayout(name='detail', record_types={'D'}, fields=[...]),\n]","handlingStrategy":"try-catch","validationCode":"# Enumerate record types present in data vs declared in layout:\ndef undeclared_record_types(layout, data: bytes) -> set[str]:\n    declared = set().union(*(r.record_types for r in layout.records))\n    seen = set()\n    for rec_start in iter_record_starts(data):  # your framing walk\n        seen.add(decode_type_field(data, rec_start))\n    return seen - declared  # non-empty predicts this error","typeGuard":null,"tryCatchPattern":"from docling.backend.ebcdic_backend import EbcdicDecodeError\ntry:\n    conv.convert(src, pipeline_options=opts)\nexcept EbcdicDecodeError as e:\n    if \"No record layout matches\" in str(e):\n        rt = extract_record_type(str(e))\n        add_record_variant_to_layout(opts.layout, rt)  # then retry\n    else:\n        raise","preventionTips":["Declare layouts for every record type the feed can emit, including rare variants.","Verify record_type_field size/offset/encoding against the copybook.","Log unexpected record types and extend layouts rather than dropping records silently."],"tags":["ebcdic","layout","record-type","decode"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}