docling-project/docling · error · ValueError

record_type_field is required for a layout with several reco

Error message

record_type_field is required for a layout with several records

What it means

Pydantic model_validator on EbcdicLayout: when the layout declares more than one record definition (self.records has length > 1) but record_type_field is None, there is no way to decide which record schema applies to each physical record, so validation fails. Multi-record EBCDIC files require a field whose value selects the record type.

Source

Thrown at docling/datamodel/backend_options.py:556

        ]

    @property
    def prefix_size(self) -> int:
        """Length in bytes of the prefix read ahead of every record."""
        return sum(item.size for item in self.prefix_fields)

    def select(self, record_type: Optional[str]) -> Optional[EbcdicRecordLayout]:
        """Return the schema matching a record-type value, if any."""
        if self.record_type_field is None:
            return self.records[0]
        return next(
            (item for item in self.records if item.selector == record_type), None
        )

    @model_validator(mode="after")
    def _validate_records(self) -> "EbcdicLayout":
        if len(self.records) > 1 and self.record_type_field is None:
            raise ValueError(
                "record_type_field is required for a layout with several records"
            )
        if self.record_type_field is not None:
            selectors = [item.selector for item in self.records]
            if None in selectors:
                raise ValueError(
                    "every record needs a selector when record_type_field is set"
                )
            if len(set(selectors)) != len(selectors):
                raise ValueError("record selectors must be unique")
        return self


class EbcdicBackendOptions(BaseBackendOptions):
    """Options specific to the EBCDIC backend."""

    kind: Annotated[Literal["ebcdic"], Field(exclude=True, repr=False)] = "ebcdic"
    encoding: Annotated[

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Set record_type_field to the name of the field whose value distinguishes record types (e.g., record_type_field='REC_TYPE').
  2. Give every record a distinct selector value matching that field's values.
  3. If the file truly has one record format, keep only one entry in records.

Example fix

# before
layout = EbcdicLayout(
    records=[header_rec, detail_rec],  # no discriminator -> ValueError
)

# after
layout = EbcdicLayout(
    record_type_field='REC_TYPE',
    records=[
        EbcdicRecordLayout(selector='H', fields=[...]),
        EbcdicRecordLayout(selector='D', fields=[...]),
    ],
)
Defensive patterns

Strategy: validation

Validate before calling

def layout_is_coherent(records, record_type_field):
    if len(records) > 1 and record_type_field is None:
        return False
    return True

Try / catch

try:
    layout = EbcdicLayout(**cfg)
except ValidationError as e:
    if 'record_type_field is required' in str(e):
        cfg['record_type_field'] = infer_discriminator_field(cfg['records'])
        layout = EbcdicLayout(**cfg)

Prevention

When it happens

Trigger: Building an EbcdicLayout(records=[EbcdicRecordLayout(...), EbcdicRecordLayout(...)]) without setting record_type_field. Common when converting fixed-width EBCDIC files that mix header/detail/trailer record types.

Common situations: Mainframe exports (e.g., IBM system files) with multiple record formats per file; users copying a single-record example and adding a second record without adding the discriminator field.

Related errors


AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14). Data as JSON: /api/errors/6dcff4df84b1b9e4. Report an issue: GitHub.