{"record":{"id":"b3ef02f9ee90439d","repo":"docling-project/docling","slug":"unknown-ebcdic-codec-encoding-r","errorCode":null,"errorMessage":"Unknown EBCDIC codec {encoding!r}.","messagePattern":"Unknown EBCDIC codec (.+?)\\.","errorType":"exception","errorClass":"DocumentLoadError","httpStatus":null,"severity":"error","filePath":"docling/backend/ebcdic_backend.py","lineNumber":68,"sourceCode":"# Sign nibbles of packed and zoned decimals: 0xb and 0xd are negative, every\n# other value (0xa, 0xc, 0xe, 0xf and unsigned digits) is positive.\n_NEGATIVE_SIGNS = frozenset({0xB, 0xD})\n\n_DecodedValue = Union[str, int, Decimal]\n\n\nclass EbcdicDecodeError(DocumentLoadError):\n    \"\"\"A field could not be decoded with the configured layout.\"\"\"\n\n\nclass _FieldDecoder:\n    \"\"\"Decode single EBCDIC fields into Python values.\"\"\"\n\n    def __init__(self, encoding: str, strip_control_characters: bool) -> None:\n        try:\n            self._decode_text = codecs.getdecoder(encoding)\n        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} \"","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/ebcdic_backend.py#L50-L86","documentation":"The EBCDIC backend's field decoder resolves its text codec with codecs.getdecoder(encoding); if Python's codec registry does not know the name (LookupError), it raises this DocumentLoadError echoing the offending encoding string. The encoding comes from EbcdicBackendOptions.encoding (directly or via the layout file), and it must be a codec Python actually ships — EBCDIC pages exist under names like cp037, cp500, cp1026, not under friendly aliases such as 'EBCDIC-US'.","triggerScenarios":"Setting EbcdicBackendOptions(encoding='ebcdic-us') or another non-registered alias; a layout JSON/YAML whose encoding field carries a typo or vendor alias; building options from user input without validating the codec name.","commonSituations":"Copy-pasting IBM codec names (IBM-037, EBCDIC-US, ibm500) from mainframe documentation into the options; layout files authored from z/OS code pages; case or hyphen variants that are not Python codec aliases.","solutions":["Use the Python codec name for the code page: cp037 (US/Canada EBCDIC), cp500 (international #5), cp1026, cp1140... Check with python -c \"import codecs; codecs.lookup('cp037')\".","Validate the encoding before constructing the backend: codecs.lookup(name) in your own code so failures surface at config time.","Fix the layout file's encoding field to the Python-registered name.","Do not pass arbitrary 'EBCDIC-*' strings — resolve them to cpNNNN aliases first."],"exampleFix":"# before\nopts = EbcdicBackendOptions(encoding='EBCDIC-US')  # not a Python codec\n\n# after\nopts = EbcdicBackendOptions(encoding='cp037')  # US EBCDIC code page","handlingStrategy":"validation","validationCode":"import codecs\n\ndef valid_codec(name: str) -> bool:\n    try:\n        codecs.lookup(name)\n        return True\n    except LookupError:\n        return False\n\nassert valid_codec(\"cp037\")       # ok\nassert not valid_codec(\"EBCDIC-US\")  # will fail -> fix config before converting","typeGuard":null,"tryCatchPattern":"from docling.exceptions import DocumentLoadError\ntry:\n    conv.convert(src, pipeline_options=opts)\nexcept DocumentLoadError as e:\n    if \"Unknown EBCDIC codec\" in str(e):\n        opts.encoding = \"cp037\"  # map alias -> Python codec, then retry\n        conv.convert(src, pipeline_options=opts)\n    else:\n        raise","preventionTips":["Validate encoding names with codecs.lookup() when options come from config files.","Use Python cpNNNN codec names (cp037, cp500, cp1026, cp1140).","Centralize the alias->codec mapping instead of trusting user input."],"tags":["ebcdic","encoding","codec","configuration"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}