docling-project/docling · error · ValueError
Unsupported numpy array shape: {img.shape}
Error message
Unsupported numpy array shape: {img.shape} What it means
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.
Source
Thrown at docling/models/vlm_pipeline_models/hf_transformers_model.py:266
Batched inference for Hugging Face Image-Text-to-Text VLMs (e.g., SmolDocling / SmolVLM).
- Lets the processor handle all padding & batching for text+images.
- Trims generated sequences per row using attention_mask (no pad-id fallbacks).
- Keeps your formulate_prompt() exactly as-is.
"""
import numpy as np
import torch
from PIL import Image as PILImage
# -- Normalize images to RGB PIL
pil_images: list[Image] = []
for img in image_batch:
if isinstance(img, np.ndarray):
if img.ndim == 3 and img.shape[2] in (3, 4):
pil_img = PILImage.fromarray(img.astype(np.uint8))
elif img.ndim == 2:
pil_img = PILImage.fromarray(img.astype(np.uint8), mode="L")
else:
raise ValueError(f"Unsupported numpy array shape: {img.shape}")
else:
pil_img = img
if pil_img.mode != "RGB":
pil_img = pil_img.convert("RGB")
pil_images.append(pil_img)
if not pil_images:
return
# -- Normalize prompts (1 per image)
if isinstance(prompt, str):
user_prompts = [prompt] * len(pil_images)
else:
if len(prompt) != len(pil_images):
raise ValueError(
f"Number of prompts ({len(prompt)}) must match number of images ({len(pil_images)})"
)
user_prompts = promptView on GitHub (pinned to 61d76f1ff3)
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
Example fix
# before batch = [torch_img.numpy() for torch_img in imgs] # each (3, H, W) # after batch = [torch_img.numpy().transpose(1, 2, 0) for torch_img in imgs] # (H, W, 3)
Defensive patterns
Strategy: type-guard
Validate before calling
import numpy as np
def as_hwc_uint8(a):
if a.ndim == 3 and a.shape[0] in (3, 4) and a.shape[2] not in (3, 4):
a = a.transpose(1, 2, 0)
if a.ndim == 3 and a.shape[2] == 1:
a = a[..., 0]
assert a.ndim == 2 or (a.ndim == 3 and a.shape[2] in (3, 4)), a.shape
return a.astype(np.uint8)
images = [as_hwc_uint8(im) for im in images] Type guard
import numpy as np
def is_supported_raster(a: np.ndarray) -> bool:
return a.ndim == 2 or (a.ndim == 3 and a.shape[2] in (3, 4)) Try / catch
try:
model(pages, prompt)
except ValueError as e:
if 'Unsupported numpy array shape' in str(e):
raise # shapes are batch-wide; fix at source with as_hwc_uint8
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Unsupported numpy array shape: {image.shape}
- Unsupported numpy array shape: {image.shape}
- Unsupported numpy array shape: {image.shape}
- Unknown prompt style `{self.vlm_options.transformers_prompt_
- Unsupported numpy array shape: {img.shape}
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/2b6f6f80d057257d.
Report an issue: GitHub.