{"record":{"id":"a031e4e3ec51b52d","repo":"docling-project/docling","slug":"cannot-mix-legacy-picture-description-options-pic","errorCode":null,"errorMessage":"Cannot mix legacy picture description options (picture_description_local/api) with new options (picture_description_preset/custom_config). Please use only one approach.","messagePattern":"Cannot mix legacy picture description options \\(picture_description_local/api\\) with new options \\(picture_description_preset/custom_config\\)\\. Please use only one approach\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/datamodel/service/options.py","lineNumber":1055,"sourceCode":"        \"\"\"Ensure preset and custom config are mutually exclusive for picture description.\"\"\"\n        if self.picture_description_preset and self.picture_description_custom_config:\n            raise ValueError(\n                \"Cannot specify both picture_description_preset and \"\n                \"picture_description_custom_config.\"\n            )\n\n        # Check if using legacy fields with new fields\n        legacy_set = (\n            self.picture_description_local is not None\n            or self.picture_description_api is not None\n        )\n        new_set = (\n            self.picture_description_preset is not None\n            or self.picture_description_custom_config is not None\n        )\n\n        if legacy_set and new_set:\n            raise ValueError(\n                \"Cannot mix legacy picture description options (picture_description_local/api) \"\n                \"with new options (picture_description_preset/custom_config). \"\n                \"Please use only one approach.\"\n            )\n\n        # Note: Deprecation warnings are now emitted by field validators\n        # when the fields are set, not here in the model validator\n\n        return self\n\n    @model_validator(mode=\"after\")\n    def validate_code_formula_options(self) -> Self:\n        \"\"\"Ensure preset and custom config are mutually exclusive for code/formula.\"\"\"\n        if self.code_formula_preset and self.code_formula_custom_config:\n            raise ValueError(\n                \"Cannot specify both code_formula_preset and code_formula_custom_config.\"\n            )\n","sourceCodeStart":1037,"sourceCodeEnd":1073,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/datamodel/service/options.py#L1037-L1073","documentation":"Model validator on the service options: legacy picture description fields (picture_description_local, picture_description_api) cannot be mixed with new-style fields (picture_description_preset, picture_description_custom_config). As with the VLM fields, docling migrated this configuration surface and rejects half-migrated payloads that set keys from both generations.","triggerScenarios":"Options containing picture_description_local or picture_description_api together with picture_description_preset or picture_description_custom_config — e.g., legacy client payload plus new deployment defaults, or a config migration that added the new keys without removing the old ones.","commonSituations":"Service upgrades where stored request templates still carry picture_description_api (deprecated) while new tooling injects presets; gradual migration of client fleets hitting the new validation.","solutions":["Complete the migration: remove picture_description_local/picture_description_api and use only preset or custom_config.","If staying legacy temporarily, ensure no preset/custom_config keys are set.","Add a pre-flight payload check rejecting mixed-generation picture-description keys."],"exampleFix":"# before\n{'picture_description_api': {...}, 'picture_description_preset': 'default'}  # ValueError\n\n# after\n{'picture_description_preset': 'default'}","handlingStrategy":"validation","validationCode":"LEGACY = ('picture_description_local', 'picture_description_api')\nNEW = ('picture_description_preset', 'picture_description_custom_config')\n\ndef picture_generations_not_mixed(o: dict) -> bool:\n    return not (any(o.get(k) is not None for k in LEGACY)\n                and any(o.get(k) is not None for k in NEW))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Migrate picture-description config fully to preset/custom_config.","Purge deprecated picture_description_local/api keys from stored templates.","Lint payloads for mixed-generation keys before submitting to the service."],"tags":["service","picture-description","validation","migration","deprecation"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}