{"record":{"id":"d75b35a7f920b5bd","repo":"docling-project/docling","slug":"cannot-decode-field-field-name-r-of-type-field","errorCode":null,"errorMessage":"Cannot decode field {field.name!r} of type {field.type.value} from {data.hex()!r}.","messagePattern":"Cannot decode field (.+?) of type (.+?) from (.+?)\\.","errorType":"exception","errorClass":"EbcdicDecodeError","httpStatus":null,"severity":"error","filePath":"docling/backend/ebcdic_backend.py","lineNumber":85,"sourceCode":"        except LookupError as exc:\n            raise DocumentLoadError(f\"Unknown EBCDIC codec {encoding!r}.\") from exc\n        self._strip_control_characters = strip_control_characters\n        self._decoders: dict[EbcdicFieldType, Callable[[bytes], _DecodedValue]] = {\n            EbcdicFieldType.STRING: self._string,\n            EbcdicFieldType.INTEGER: lambda data: self._binary(data, signed=True),\n            EbcdicFieldType.UNSIGNED_INTEGER: lambda data: self._binary(\n                data, signed=False\n            ),\n            EbcdicFieldType.PACKED_DECIMAL: self._packed_decimal,\n            EbcdicFieldType.ZONED_DECIMAL: self._zoned_decimal,\n        }\n\n    def decode(self, data: bytes, field: EbcdicField) -> _DecodedValue:\n        \"\"\"Decode the bytes of one field as described by its layout.\"\"\"\n        try:\n            value = self._decoders[field.type](data)\n        except (ArithmeticError, LookupError, UnicodeError, ValueError) as exc:\n            raise EbcdicDecodeError(\n                f\"Cannot decode field {field.name!r} of type {field.type.value} \"\n                f\"from {data.hex()!r}.\"\n            ) from exc\n        if isinstance(value, int) and field.scale:\n            return Decimal(value).scaleb(-field.scale)\n        return value\n\n    def _string(self, data: bytes) -> str:\n        text, _ = self._decode_text(data)\n        if self._strip_control_characters:\n            text = _CONTROL_CHARACTERS.sub(\"\", text)\n        return text.strip()\n\n    @staticmethod\n    def _binary(data: bytes, signed: bool) -> int:\n        return int.from_bytes(data, byteorder=\"big\", signed=signed)\n\n    @staticmethod","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/ebcdic_backend.py#L67-L103","documentation":"EbcdicDecodeError (a DocumentLoadError subclass) raised when decoding a single field's bytes fails: the per-type decoder (string via the configured codec, packed/zoned decimal digit handling, binary int conversion) raised ArithmeticError, LookupError, UnicodeError, or ValueError. The message names the field, its declared type, and the raw hex bytes, which is exactly what you need to tell a layout mismatch (bytes don't fit the declared type) from an encoding problem.","triggerScenarios":"A layout whose field offsets/sizes/types do not match the actual data: a field declared PACKED_DECIMAL whose bytes have an invalid sign nibble; a STRING field containing bytes unmappable in the configured codec (UnicodeError); an INTEGER field wider than expected; field boundaries shifted because an earlier field's size is wrong.","commonSituations":"Hand-written layout files transcribed from a COBOL copybook with an off-by-one; copybook REDEFINES or COMP-3 packing not translated correctly; using the wrong EBCDIC code page for the site's country; files from a different mainframe system version than the layout documents.","solutions":["Use the hex bytes in the message: check whether they are plausible for the declared type (e.g. packed decimal must end in a valid sign nibble C/D/F).","Re-derive the layout from the authoritative copybook, paying attention to COMP/COMP-3 usage, SYNC padding, and REDEFINES.","If UnicodeError is chained (check e.__cause__), switch EbcdicBackendOptions.encoding to the correct code page (cp037 vs cp500 etc.).","Verify preceding field sizes — a wrong size earlier shifts every later field and produces this error on an innocent field."],"exampleFix":"# before (layout mismatch)\nopts = EbcdicBackendOptions(\n    layout=EbcdicLayout(\n        records=[EbcdicRecordLayout(name='hdr', fields=[\n            EbcdicField(name='AMOUNT', type=EbcdicFieldType.ZONED_DECIMAL, size=5),\n        ])],\n    ),\n    encoding='cp037',\n)\n# AMOUNT is really COMP-3 packed -> decode error\n\n# after\nEbcdicField(name='AMOUNT', type=EbcdicFieldType.PACKED_DECIMAL, size=3),  # match copybook","handlingStrategy":"try-catch","validationCode":"# Decode a sample record with your layout before batch runs:\ndef layout_smokescreen(layout, sample_bytes: bytes) -> list[str] | None:\n    try:\n        return decode_record(layout, sample_bytes)  # your thin wrapper over the backend\n    except Exception:\n        return None\n\nif layout_smokescreen(layout, first_record_bytes) is None:\n    raise ConfigError(\"EBCDIC layout does not match sample data\")","typeGuard":null,"tryCatchPattern":"from docling.backend.ebcdic_backend import EbcdicDecodeError\ntry:\n    conv.convert(src, pipeline_options=opts)\nexcept EbcdicDecodeError as e:\n    field, hexbytes = parse_message(str(e))  # field name + hex payload are embedded\n    log.error(\"layout mismatch at %s bytes=%s cause=%r\", field, hexbytes, e.__cause__)\n    quarantine(src)","preventionTips":["Generate layouts from authoritative COBOL copybooks, not by hand.","Smoke-test the layout against a known-good sample record before batch runs.","Watch e.__cause__: UnicodeError means wrong code page; ValueError/ArithmeticError mean wrong field type/size."],"tags":["ebcdic","layout","decode","mainframe"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}