docling-project/docling · error · ValueError

every record needs a selector when record_type_field is set

Error message

every record needs a selector when record_type_field is set

What it means

Pydantic model_validator on EbcdicLayout: once record_type_field is set, every entry in records must carry a non-None selector, because select() matches records by item.selector == record_type. A record without a selector can never be chosen, so the layout is rejected.

Source

Thrown at docling/datamodel/backend_options.py:562

    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[
        str,
        Field(
            description=(
                "Python codec used to decode character data, e.g. `cp037` "
                "(US/Canada), `cp500` (international) or `cp1140` (euro)."
            )

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Set an explicit selector on every record in records, each matching a concrete value of record_type_field.
  2. Audit the layout dict/JSON for missing 'selector' keys before constructing EbcdicLayout.
  3. Keep a test that asserts all(r.selector for r in layout.records) when record_type_field is set.

Example fix

# before
EbcdicLayout(record_type_field='REC_TYPE', records=[
    EbcdicRecordLayout(selector='01', fields=...),
    EbcdicRecordLayout(fields=...),  # selector missing -> ValueError
])

# after
EbcdicLayout(record_type_field='REC_TYPE', records=[
    EbcdicRecordLayout(selector='01', fields=...),
    EbcdicRecordLayout(selector='02', fields=...),
])
Defensive patterns

Strategy: validation

Validate before calling

def all_records_have_selector(records, record_type_field) -> bool:
    if record_type_field is None:
        return True
    return all(r.get('selector') is not None for r in records)

Prevention

When it happens

Trigger: Setting record_type_field='REC_TYPE' but leaving one EbcdicRecordLayout's selector as None (the default) — e.g., adding a new record type and forgetting its selector.

Common situations: Iteratively building layouts: start with selectors on all records, then append a record copied from a template without filling selector; JSON layout files where a selector key was dropped.

Related errors


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