docling-project/docling · error · ValueError

ThreadedLayoutVlmPipeline only supports DOCTAGS response for

Error message

ThreadedLayoutVlmPipeline only supports DOCTAGS response format, but got {self.vlm_options.response_format}. Please set vlm_options.response_format=ResponseFormat.DOCTAGS

What it means

Pydantic ValidationError raised by the model_validator on ThreadedLayoutVlmPipelineOptions: this experimental threaded pipeline can only consume VLM output in DOCTAGS format, so any other vlm_options.response_format is rejected at options-construction time.

Source

Thrown at docling/experimental/datamodel/threaded_layout_vlm_pipeline_options.py:45

        GRANITEDOCLING_2STAGE_TRANSFORMERS
    )

    # Layout model configuration
    layout_options: BaseLayoutOptions = Field(
        default_factory=lambda: LayoutObjectDetectionOptions(skip_cell_assignment=True),
    )

    # Threading and batching controls
    layout_batch_size: int = 4
    vlm_batch_size: int = 4
    batch_timeout_seconds: float = 2.0
    queue_max_size: int = 50

    @model_validator(mode="after")
    def validate_response_format(self):
        """Validate that VLM response format is DOCTAGS (required for this pipeline)."""
        if self.vlm_options.response_format != ResponseFormat.DOCTAGS:
            raise ValueError(
                f"ThreadedLayoutVlmPipeline only supports DOCTAGS response format, "
                f"but got {self.vlm_options.response_format}. "
                f"Please set vlm_options.response_format=ResponseFormat.DOCTAGS"
            )
        return self

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Set response_format=ResponseFormat.DOCTAGS on the nested vlm_options before constructing ThreadedLayoutVlmPipelineOptions.
  2. Do not share one VlmOptions instance across pipeline types; clone and adjust per pipeline.
  3. If you need MARKDOWN/JSON output, use the standard VlmPipeline instead of the threaded variant.

Example fix

# before
vlm_opts = VlmOptions(response_format=ResponseFormat.MARKDOWN)
opts = ThreadedLayoutVlmPipelineOptions(vlm_options=vlm_opts)  # ValidationError

# after
vlm_opts = VlmOptions(response_format=ResponseFormat.DOCTAGS)
opts = ThreadedLayoutVlmPipelineOptions(vlm_options=vlm_opts)
Defensive patterns

Strategy: validation

Validate before calling

from docling.datamodel.pipeline_options_vlm_model import ResponseFormat
if vlm_opts.response_format != ResponseFormat.DOCTAGS:
    vlm_opts = vlm_opts.model_copy(update={'response_format': ResponseFormat.DOCTAGS})

Type guard

def is_doctags(opts) -> bool:
    return getattr(getattr(opts, 'vlm_options', opts), 'response_format', None) is not None and opts.vlm_options.response_format == ResponseFormat.DOCTAGS

Try / catch

from pydantic import ValidationError
try:
    opts = ThreadedLayoutVlmPipelineOptions(vlm_options=vlm_opts)
except ValidationError as e:
    if 'DOCTAGS' in str(e):
        vlm_opts.response_format = ResponseFormat.DOCTAGS
        opts = ThreadedLayoutVlmPipelineOptions(vlm_options=vlm_opts)

Prevention

When it happens

Trigger: Building ThreadedLayoutVlmPipelineOptions with vlm_options whose response_format is MARKDOWN or JSON (e.g. reusing VlmPipelineOptions configured for the standard VLM pipeline).

Common situations: Copy-pasting options from StandardPdfPipeline VLM usage where MARKDOWN is common; sharing a global vlm_options object between the standard and threaded pipelines.

Related errors


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