{"record":{"id":"2b6f6f80d057257d","repo":"docling-project/docling","slug":"unsupported-numpy-array-shape-img-shape-2b6f6f","errorCode":null,"errorMessage":"Unsupported numpy array shape: {img.shape}","messagePattern":"Unsupported numpy array shape: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/models/vlm_pipeline_models/hf_transformers_model.py","lineNumber":266,"sourceCode":"        Batched inference for Hugging Face Image-Text-to-Text VLMs (e.g., SmolDocling / SmolVLM).\n        - Lets the processor handle all padding & batching for text+images.\n        - Trims generated sequences per row using attention_mask (no pad-id fallbacks).\n        - Keeps your formulate_prompt() exactly as-is.\n        \"\"\"\n        import numpy as np\n        import torch\n        from PIL import Image as PILImage\n\n        # -- Normalize images to RGB PIL\n        pil_images: list[Image] = []\n        for img in image_batch:\n            if isinstance(img, np.ndarray):\n                if img.ndim == 3 and img.shape[2] in (3, 4):\n                    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        # -- Normalize prompts (1 per image)\n        if isinstance(prompt, str):\n            user_prompts = [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 number of images ({len(pil_images)})\"\n                )\n            user_prompts = prompt","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/models/vlm_pipeline_models/hf_transformers_model.py#L248-L284","documentation":"Before generation, HuggingFaceTransformersVlmModel normalizes every input to an RGB PIL image. The numpy branch accepts only (H,W), (H,W,3) and (H,W,4); anything else — channels-first (C,H,W), (H,W,1), or higher-rank arrays — raises ValueError with the offending shape.","triggerScenarios":"Passing torch-style CHW arrays, np.expand_dims-produced (H,W,1) masks, or a 4-D stacked batch ndarray where single images are expected in the image_batch iterable.","commonSituations":"Reusing preprocessing pipelines written for torch (CHW); feeding segmentation masks or depth maps with a trailing 1-channel dimension; passing float arrays that were never squeezed/converted.","solutions":["Convert CHW to HWC with img.transpose(1,2,0)","Squeeze trailing singleton channels: img.squeeze() for (H,W,1)","Pass docling Image/PIL objects directly and let Docling handle page rasters"],"exampleFix":"# before\nbatch = [torch_img.numpy() for torch_img in imgs]  # each (3, H, W)\n# after\nbatch = [torch_img.numpy().transpose(1, 2, 0) for torch_img in imgs]  # (H, W, 3)","handlingStrategy":"type-guard","validationCode":"import numpy as np\n\ndef as_hwc_uint8(a):\n    if a.ndim == 3 and a.shape[0] in (3, 4) and a.shape[2] not in (3, 4):\n        a = a.transpose(1, 2, 0)\n    if a.ndim == 3 and a.shape[2] == 1:\n        a = a[..., 0]\n    assert a.ndim == 2 or (a.ndim == 3 and a.shape[2] in (3, 4)), a.shape\n    return a.astype(np.uint8)\n\nimages = [as_hwc_uint8(im) for im in images]","typeGuard":"import numpy as np\n\ndef is_supported_raster(a: np.ndarray) -> bool:\n    return a.ndim == 2 or (a.ndim == 3 and a.shape[2] in (3, 4))","tryCatchPattern":"try:\n    model(pages, prompt)\nexcept ValueError as e:\n    if 'Unsupported numpy array shape' in str(e):\n        raise  # shapes are batch-wide; fix at source with as_hwc_uint8\n    raise","preventionTips":["Keep one normalization function for all rasters entering Docling","Convert torch outputs with .permute(1,2,0) before handing them over","Unit-test your image loader against (H,W),(H,W,3),(H,W,4) acceptance"],"tags":["numpy","image","shape","transformers","vlm"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}