{"record":{"id":"e76bb0de930656bb","repo":"docling-project/docling","slug":"number-of-prompts-len-prompt-must-match-numbe","errorCode":null,"errorMessage":"Number of prompts ({len(prompt)}) must match number of images ({len(pil_images)})","messagePattern":"Number of prompts \\((.+?)\\) must match number of images \\((.+?)\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/models/extraction/transformers_extraction_model.py","lineNumber":143,"sourceCode":"                    pil_img = PILImage.fromarray(img.astype(np.uint8))\n                elif img.ndim == 2:\n                    pil_img = PILImage.fromarray(img.astype(np.uint8), mode=\"L\")\n                else:\n                    raise ValueError(f\"Unsupported numpy array shape: {img.shape}\")\n            else:\n                pil_img = img\n            if pil_img.mode != \"RGB\":\n                pil_img = pil_img.convert(\"RGB\")\n            pil_images.append(pil_img)\n\n        if not pil_images:\n            return\n\n        if isinstance(prompt, str):\n            templates = [prompt] * len(pil_images)\n        else:\n            if len(prompt) != len(pil_images):\n                raise ValueError(\n                    f\"Number of prompts ({len(prompt)}) must match \"\n                    f\"number of images ({len(pil_images)})\"\n                )\n            templates = prompt\n\n        # Build tokenized inputs based on prompt style\n        if self.prompt_style == ExtractionPromptStyle.NUEXTRACT:\n            processor_inputs = build_nuextract_inputs(\n                processor=self.processor,\n                images=pil_images,\n                templates=templates,\n                device=self.device,\n                extra_processor_kwargs=self.vlm_options.extra_processor_kwargs,\n            )\n        else:\n            processor_inputs = build_granite_vision_inputs(\n                processor=self.processor,\n                images=pil_images,","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/models/extraction/transformers_extraction_model.py#L125-L161","documentation":"Thrown by TransformersExtractionModel.process_images when the caller passes a list of prompts whose length differs from the number of images produced from the batch. A single string prompt is broadcast to all images, but a list must be one-to-one with the image batch. The error surfaces before any tokenization or model inference happens.","triggerScenarios":"Calling process_images(image_batch, prompt=[...]) with len(prompt) != number of valid images in image_batch. Note that a batch containing zero valid images returns early, so the mismatch only occurs with >=1 image; also numpy arrays that are not 2D or 3D-with-3/4-channels raise a different error first.","commonSituations":"Building per-image templates for NuExtract-style extraction (each image needs its own schema template) and dropping or adding one entry; filtering images out of a batch but forgetting to filter the matching prompt; off-by-one slicing of prompts.","solutions":["If all images should use the same prompt, pass a plain string instead of a list (it is broadcast automatically).","Otherwise assert len(prompts) == len(images) before the call and fix the construction of the prompt list (usually a zip/filter mismatch upstream).","Build prompts and images together in one pass (e.g. zip(images, prompts)) so they cannot diverge."],"exampleFix":"# before\nprompts = [TEMPLATE] * 5\nresults = model.process_images(images[:4], prompts)  # 5 prompts, 4 images\n\n# after\nresults = model.process_images(images, TEMPLATE)  # broadcast one string to all images\n\n# or, per-image prompts:\nassert len(prompts) == len(images)\nresults = model.process_images(images, prompts)","handlingStrategy":"validation","validationCode":"if isinstance(prompts, list):\n    assert len(prompts) == len(list(image_batch)), (\n        f'{len(prompts)} prompts vs {len(image_batch)} images'\n    )","typeGuard":"from typing import Union, List\nfrom docling.datamodel.base_settings import Image\n\ndef is_valid_prompt(prompt: Union[str, List[str]], n_images: int) -> bool:\n    return isinstance(prompt, str) or len(prompt) == n_images","tryCatchPattern":"try:\n    results = model.process_images(images, prompts)\nexcept ValueError as e:\n    if 'must match' in str(e):\n        results = model.process_images(images, prompts[:len(images)])  # or fix upstream\n    else:\n        raise","preventionTips":["Pass a single string prompt unless each image truly needs its own template.","Build images and prompts with a single zip() so they stay aligned.","Add an assertion on lengths at the batch-construction site, not at model call time."],"tags":["validation","extraction","vision-model","batching"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}