{"record":{"id":"f74238b1134ebe07","repo":"docling-project/docling","slug":"cannot-specify-both-picture-description-preset-and","errorCode":null,"errorMessage":"Cannot specify both picture_description_preset and picture_description_custom_config.","messagePattern":"Cannot specify both picture_description_preset and picture_description_custom_config\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/datamodel/service/options.py","lineNumber":1039,"sourceCode":"            or self.vlm_pipeline_custom_config is not None\n        )\n\n        if legacy_set and new_set:\n            raise ValueError(\n                \"Cannot mix legacy VLM options (vlm_pipeline_model*) with new options \"\n                \"(vlm_pipeline_preset/custom_config). 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_picture_description_options(self) -> Self:\n        \"\"\"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). \"","sourceCodeStart":1021,"sourceCodeEnd":1057,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/datamodel/service/options.py#L1021-L1057","documentation":"Model validator on the service options: picture_description_preset and picture_description_custom_config are the new-style, mutually exclusive ways to configure picture description. Supplying both is rejected because a preset already determines the full configuration and a custom config contradicts it.","triggerScenarios":"Options containing both picture_description_preset and picture_description_custom_config — commonly a default preset from a shared template plus custom tuning added per request.","commonSituations":"Config templates with an opinionated default preset; teams layering custom config objects on top of presets instead of editing the preset contents.","solutions":["Send only one of picture_description_preset or picture_description_custom_config.","To customize a preset, materialize it into a custom_config, edit, and drop the preset key.","Clean merged config dicts of one of the two keys before submission."],"exampleFix":"# before\n{'picture_description_preset': 'default', 'picture_description_custom_config': {...}}  # ValueError\n\n# after\n{'picture_description_custom_config': {...}}","handlingStrategy":"validation","validationCode":"def picture_preset_exclusive(o: dict) -> bool:\n    return not (o.get('picture_description_preset') and o.get('picture_description_custom_config'))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Send either picture_description_preset or picture_description_custom_config.","Materialize presets into custom_config when tuning is needed.","Remove one key when merging template configs."],"tags":["service","picture-description","validation","mutual-exclusion"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}