{"record":{"id":"ea0035a369c2291c","repo":"docling-project/docling","slug":"set-either-layout-or-layout-file-not-both","errorCode":null,"errorMessage":"set either layout or layout_file, not both","messagePattern":"set either layout or layout_file, not both","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/datamodel/backend_options.py","lineNumber":602,"sourceCode":"        Optional[EbcdicLayout], Field(description=\"Parsing rules for the file.\")\n    ] = None\n    layout_file: Annotated[\n        Optional[Path],\n        Field(description=\"Path to a JSON file holding the parsing rules.\"),\n    ] = None\n    max_records: Annotated[\n        Optional[PositiveInt],\n        Field(description=\"Stop after this many records. Unset reads the whole file.\"),\n    ] = None\n    strip_control_characters: Annotated[\n        bool,\n        Field(description=\"Drop control characters from decoded character data.\"),\n    ] = True\n\n    @model_validator(mode=\"after\")\n    def _validate_layout_source(self) -> \"EbcdicBackendOptions\":\n        if self.layout is not None and self.layout_file is not None:\n            raise ValueError(\"set either layout or layout_file, not both\")\n        return self\n\n\nBackendOptions = Annotated[\n    Union[\n        DeclarativeBackendOptions,\n        EbcdicBackendOptions,\n        EpubBackendOptions,\n        HTMLBackendOptions,\n        MarkdownBackendOptions,\n        PdfBackendOptions,\n        ThreadedDoclingParseBackendOptions,\n        MetsGbsBackendOptions,\n        MsExcelBackendOptions,\n        MsPowerpointBackendOptions,\n        MsWordBackendOptions,\n        OdsBackendOptions,\n        LatexBackendOptions,","sourceCodeStart":584,"sourceCodeEnd":620,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/datamodel/backend_options.py#L584-L620","documentation":"Pydantic model_validator on EbcdicBackendOptions: layout (an inline EbcdicLayout object) and layout_file (a path to a layout definition) are the two mutually exclusive ways to supply the record schema. Setting both is ambiguous, so the model raises immediately.","triggerScenarios":"Constructing EbcdicBackendOptions(layout=my_layout, layout_file=Path('layout.json')) — typically when a shared config template already sets layout_file and code also passes an inline layout (or vice versa).","commonSituations":"Pipelines built on a base options object that includes layout_file, then per-run code adds a layout override; merging CLI flags with programmatic options.","solutions":["Keep exactly one source: either the inline layout object or layout_file, not both.","If overriding, explicitly set the other to None: EbcdicBackendOptions(layout=new_layout, layout_file=None).","When loading from a shared config, pop the unused key before constructing options."],"exampleFix":"# before\nopts = EbcdicBackendOptions(layout=layout, layout_file=Path('layout.json'))  # ValueError\n\n# after\nopts = EbcdicBackendOptions(layout=layout)","handlingStrategy":"validation","validationCode":"cfg.pop('layout_file', None)  # or cfg.pop('layout', None)\nopts = EbcdicBackendOptions(**cfg)  # exactly one layout source","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick one configuration style (inline layout vs layout_file) per project.","When overriding options, explicitly null out the alternative field.","Clean merged config dicts of one layout key before construction."],"tags":["ebcdic","validation","pydantic","mutual-exclusion"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}