{"record":{"id":"c0985beb00d5be89","repo":"docling-project/docling","slug":"cannot-specify-both-picture-classification-preset","errorCode":null,"errorMessage":"Cannot specify both picture_classification_preset and picture_classification_custom_config.","messagePattern":"Cannot specify both picture_classification_preset and picture_classification_custom_config\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/datamodel/service/options.py","lineNumber":1092,"sourceCode":"        return self\n\n    @model_validator(mode=\"after\")\n    def validate_layout_options(self) -> Self:\n        \"\"\"Ensure preset and custom config are mutually exclusive for layout.\"\"\"\n        if self.layout_preset and self.layout_custom_config:\n            raise ValueError(\n                \"Cannot specify both layout_preset and layout_custom_config.\"\n            )\n        return self\n\n    @model_validator(mode=\"after\")\n    def validate_picture_classification_options(self) -> Self:\n        \"\"\"Ensure preset and custom config are mutually exclusive for picture classification.\"\"\"\n        if (\n            self.picture_classification_preset\n            and self.picture_classification_custom_config\n        ):\n            raise ValueError(\n                \"Cannot specify both picture_classification_preset and \"\n                \"picture_classification_custom_config.\"\n            )\n        return self\n\n    @model_validator(mode=\"after\")\n    def validate_ocr_options(self) -> Self:\n        \"\"\"Handle deprecated ocr_engine and sync to ocr_preset.\"\"\"\n        # If ocr_engine is explicitly set (not default), sync to ocr_preset\n        if (\n            hasattr(self, \"__pydantic_fields_set__\")\n            and \"ocr_engine\" in self.__pydantic_fields_set__\n            and \"ocr_preset\" not in self.__pydantic_fields_set__\n        ):\n            warnings.warn(\n                \"ocr_engine is deprecated and will be removed in a future version. \"\n                \"Use ocr_preset instead.\",\n                DeprecationWarning,","sourceCodeStart":1074,"sourceCodeEnd":1110,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/datamodel/service/options.py#L1074-L1110","documentation":"A Pydantic model validator rejects service options that set both picture_classification_preset and picture_classification_custom_config. The picture classification stage is configured either by a named preset or by a custom config, and supplying both is a modeling error caught during validation.","triggerScenarios":"Building the options model with both picture_classification_preset and picture_classification_custom_config set, e.g. ConvertOptions(picture_classification_preset='default', picture_classification_custom_config={'labels': [...]}).","commonSituations":"Reusing a full example config that contained a preset while adding a custom classifier config for a new use case; config inheritance where a base sets the preset and a child adds the custom dict; GUI form builders that submit every field regardless of which section the user filled in.","solutions":["Send only one of picture_classification_preset or picture_classification_custom_config.","If the custom config was copied from a preset just to tweak one value, remove the custom config and use the preset.","Validate the outgoing payload shape in a shared helper so the pair is mutually exclusive by construction."],"exampleFix":"# before\nopts = ConvertOptions(\n    picture_classification_preset=\"default\",\n    picture_classification_custom_config={\"labels\": [\"chart\"]},\n)\n\n# after\nopts = ConvertOptions(\n    picture_classification_custom_config={\"labels\": [\"chart\"]},\n)","handlingStrategy":"validation","validationCode":"def assert_picture_classification(opts: dict) -> None:\n    assert not (\n        opts.get(\"picture_classification_preset\")\n        and opts.get(\"picture_classification_custom_config\")\n    ), \"picture_classification_preset and picture_classification_custom_config are mutually exclusive\"","typeGuard":null,"tryCatchPattern":"try:\n    ConvertOptions(**cfg)\nexcept ValidationError as e:\n    if \"picture_classification\" in str(e):\n        # strip whichever field the user did not intend\n        raise ValueError(\"Pick preset OR custom config for picture classification\") from e\n    raise","preventionTips":["Never merge preset and custom keys when composing configs from fragments.","Unit-test your config builder to prove the pair never co-occurs."],"tags":["pydantic","validation","configuration","picture-classification","mutually-exclusive"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}