docling-project/docling · error · ValueError

Cannot specify both vlm_pipeline_preset and vlm_pipeline_cus

Error message

Cannot specify both vlm_pipeline_preset and vlm_pipeline_custom_config. Please use one or the other.

What it means

Model validator on the service options: vlm_pipeline_preset (a named preset) and vlm_pipeline_custom_config (a full custom configuration) are the two new-style ways to configure the VLM pipeline and are mutually exclusive — a preset already fixes the config, so supplying both is contradictory.

Source

Thrown at docling/datamodel/service/options.py:1008

            opt is not None
            for opt in (
                self.vlm_pipeline_model,
                self.vlm_pipeline_model_local,
                self.vlm_pipeline_model_api,
            )
        )
        if num_not_nan > 1:
            raise ValueError(
                "The parameters vlm_pipeline_model, vlm_pipeline_model_local and vlm_pipeline_model_api are mutually exclusive, only one of them can be set."
            )

        return self

    @model_validator(mode="after")
    def validate_vlm_pipeline_options(self) -> Self:
        """Ensure preset and custom config are mutually exclusive for VLM pipeline."""
        if self.vlm_pipeline_preset and self.vlm_pipeline_custom_config:
            raise ValueError(
                "Cannot specify both vlm_pipeline_preset and vlm_pipeline_custom_config. "
                "Please use one or the other."
            )

        # Check if using legacy fields with new fields
        legacy_set = (
            self.vlm_pipeline_model is not None
            or self.vlm_pipeline_model_local is not None
            or self.vlm_pipeline_model_api is not None
        )
        new_set = (
            self.vlm_pipeline_preset is not None
            or self.vlm_pipeline_custom_config is not None
        )

        if legacy_set and new_set:
            raise ValueError(
                "Cannot mix legacy VLM options (vlm_pipeline_model*) with new options "

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Choose one: either the preset name or the fully custom config object.
  2. If you need to tweak a preset, copy its contents into vlm_pipeline_custom_config, modify, and drop the preset field.
  3. Strip default preset values from templates before adding custom configs.

Example fix

# before
{'vlm_pipeline_preset': 'vlm', 'vlm_pipeline_custom_config': {...}}  # ValueError

# after
{'vlm_pipeline_custom_config': {...}}
Defensive patterns

Strategy: validation

Validate before calling

def vlm_preset_exclusive(o: dict) -> bool:
    return not (o.get('vlm_pipeline_preset') and o.get('vlm_pipeline_custom_config'))

Prevention

When it happens

Trigger: Request options containing both vlm_pipeline_preset='...' and vlm_pipeline_custom_config={...}, typically from a config template that fills a default preset while code adds a custom config for tuning.

Common situations: Teams sharing a base options JSON with a preset, then developers layering custom_config tweaks on top instead of forking the preset.

Related errors


AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14). Data as JSON: /api/errors/398e3b53e316d901. Report an issue: GitHub.