docling-project/docling · error · ValueError
record selectors must be unique
Error message
record selectors must be unique
What it means
Pydantic model_validator on EbcdicLayout: selectors across records must be unique. Duplicate selectors make select()'s next() ambiguous (first match silently wins), so the model rejects the layout rather than allow silent misinterpretation of records.
Source
Thrown at docling/datamodel/backend_options.py:566
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)."
)
),
] = "cp037"
layout: Annotated[
Optional[EbcdicLayout], Field(description="Parsing rules for the file.")View on GitHub (pinned to 61d76f1ff3)
Solutions
- Give each record a distinct selector value matching the actual codes in the file.
- If two codes map to the same schema, either merge them or use distinct selectors and adjust the source data expectation.
- Programmatically check len({r.selector for r in records}) == len(records) before building the model.
Example fix
# before records=[rec(selector='D', ...), rec(selector='D', ...)] # duplicate -> ValueError # after records=[rec(selector='D1', ...), rec(selector='D2', ...)]
Defensive patterns
Strategy: validation
Validate before calling
def selectors_unique(records) -> bool:
sel = [r.selector for r in records if r.selector is not None]
return len(set(sel)) == len(sel) Prevention
- Assert selector uniqueness in layout unit tests.
- Beware look-alike codes ('O' vs '0', 'l' vs '1') when hand-authoring layouts.
- Generate layouts from the source system's record-type table to avoid duplicates.
When it happens
Trigger: Two EbcdicRecordLayout entries with the same selector string (e.g., both 'D') while record_type_field is set; copy-pasting a record definition and changing fields but not selector; data-entry typos like 'O' vs '0' colliding after normalization.
Common situations: Hand-maintained layout files for legacy EBCDIC exports where record-type codes were duplicated by mistake; generated layouts from a spreadsheet where two rows share a type code.
Related errors
- record_type_field is required for a layout with several reco
- every record needs a selector when record_type_field is set
- set either layout or layout_file, not both
- Invalid device option. Use `auto`, `cpu`, `mps`, `xpu`, `cud
- Model `{self.repo_id}` is English-only and does not support
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/cb05f512724bceb2.
Report an issue: GitHub.