docling-project/docling · error · EbcdicDecodeError
Cannot decode field {field.name!r} of type {field.type.value
Error message
Cannot decode field {field.name!r} of type {field.type.value} from {data.hex()!r}. What it means
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.
Source
Thrown at docling/backend/ebcdic_backend.py:85
except LookupError as exc:
raise DocumentLoadError(f"Unknown EBCDIC codec {encoding!r}.") from exc
self._strip_control_characters = strip_control_characters
self._decoders: dict[EbcdicFieldType, Callable[[bytes], _DecodedValue]] = {
EbcdicFieldType.STRING: self._string,
EbcdicFieldType.INTEGER: lambda data: self._binary(data, signed=True),
EbcdicFieldType.UNSIGNED_INTEGER: lambda data: self._binary(
data, signed=False
),
EbcdicFieldType.PACKED_DECIMAL: self._packed_decimal,
EbcdicFieldType.ZONED_DECIMAL: self._zoned_decimal,
}
def decode(self, data: bytes, field: EbcdicField) -> _DecodedValue:
"""Decode the bytes of one field as described by its layout."""
try:
value = self._decoders[field.type](data)
except (ArithmeticError, LookupError, UnicodeError, ValueError) as exc:
raise EbcdicDecodeError(
f"Cannot decode field {field.name!r} of type {field.type.value} "
f"from {data.hex()!r}."
) from exc
if isinstance(value, int) and field.scale:
return Decimal(value).scaleb(-field.scale)
return value
def _string(self, data: bytes) -> str:
text, _ = self._decode_text(data)
if self._strip_control_characters:
text = _CONTROL_CHARACTERS.sub("", text)
return text.strip()
@staticmethod
def _binary(data: bytes, signed: bool) -> int:
return int.from_bytes(data, byteorder="big", signed=signed)
@staticmethodView on GitHub (pinned to 61d76f1ff3)
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.
Example fix
# before (layout mismatch)
opts = EbcdicBackendOptions(
layout=EbcdicLayout(
records=[EbcdicRecordLayout(name='hdr', fields=[
EbcdicField(name='AMOUNT', type=EbcdicFieldType.ZONED_DECIMAL, size=5),
])],
),
encoding='cp037',
)
# AMOUNT is really COMP-3 packed -> decode error
# after
EbcdicField(name='AMOUNT', type=EbcdicFieldType.PACKED_DECIMAL, size=3), # match copybook Defensive patterns
Strategy: try-catch
Validate before calling
# Decode a sample record with your layout before batch runs:
def layout_smokescreen(layout, sample_bytes: bytes) -> list[str] | None:
try:
return decode_record(layout, sample_bytes) # your thin wrapper over the backend
except Exception:
return None
if layout_smokescreen(layout, first_record_bytes) is None:
raise ConfigError("EBCDIC layout does not match sample data") Try / catch
from docling.backend.ebcdic_backend import EbcdicDecodeError
try:
conv.convert(src, pipeline_options=opts)
except EbcdicDecodeError as e:
field, hexbytes = parse_message(str(e)) # field name + hex payload are embedded
log.error("layout mismatch at %s bytes=%s cause=%r", field, hexbytes, e.__cause__)
quarantine(src) Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- No record layout matches record type {record_type!r}.
- Record length {length} is shorter than the {layout.prefix_si
- Input ends inside {name!r}: {end - offset} of {size} bytes l
- The EBCDIC backend needs a layout: set either EbcdicBackendO
- record_type_field is required for a layout with several reco
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/d75b35a7f920b5bd.
Report an issue: GitHub.