docling-project/docling · error · ValueError

Unsupported numpy array shape: {image.shape}

Error message

Unsupported numpy array shape: {image.shape}

What it means

ApiVlmModel's numpy-to-PIL conversion only accepts 2-D grayscale arrays (H,W) and 3-D arrays whose last dimension is 3 (RGB) or 4 (RGBA). Any other layout — e.g. channels-first (3,H,W), single-column shape (H,W,1), or 4-D batch arrays — raises this ValueError before the image is sent to the API.

Source

Thrown at docling/models/vlm_pipeline_models/api_vlm_model.py:129

                    f"Prompt list length ({len(prompt)}) must match image count ({len(images)})"
                )
            prompts = prompt

        def _process_single_image(image_prompt_pair):
            image, prompt_text = image_prompt_pair

            # Convert numpy array to PIL Image if needed
            if isinstance(image, np.ndarray):
                if image.ndim == 3 and image.shape[2] in [3, 4]:
                    from PIL import Image as PILImage

                    image = PILImage.fromarray(image.astype(np.uint8))
                elif image.ndim == 2:
                    from PIL import Image as PILImage

                    image = PILImage.fromarray(image.astype(np.uint8), mode="L")
                else:
                    raise ValueError(f"Unsupported numpy array shape: {image.shape}")

            # Ensure image is in RGB mode
            if image.mode != "RGB":
                image = image.convert("RGB")

            stop_reason = VlmStopReason.UNSPECIFIED

            if self.vlm_options.custom_stopping_criteria:
                # Instantiate any GenerationStopper classes before passing to streaming
                instantiated_stoppers = []
                for criteria in self.vlm_options.custom_stopping_criteria:
                    if isinstance(criteria, GenerationStopper):
                        instantiated_stoppers.append(criteria)
                    elif isinstance(criteria, type) and issubclass(
                        criteria, GenerationStopper
                    ):
                        instantiated_stoppers.append(criteria())
                    # Skip non-GenerationStopper criteria (should have been caught in validation)

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Transpose channels-first arrays to HWC: arr.transpose(1,2,0)
  2. Squeeze (H,W,1) to (H,W), or use the 2-D grayscale path directly
  3. Pass docling Image objects or PIL Images instead of raw arrays to skip conversion entirely

Example fix

# before
img = model_preprocessed_chw  # shape (3, 1024, 768)
out = model._process_batch([img], prompt)
# after
img = model_preprocessed_chw.transpose(1, 2, 0)  # shape (1024, 768, 3)
out = model._process_batch([img], prompt)
Defensive patterns

Strategy: type-guard

Validate before calling

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))

for a in images:
    if not is_supported_raster(a):
        raise ValueError(f'bad shape {a.shape}')

Type guard

import numpy as np

def to_hwc(a: np.ndarray) -> np.ndarray:
    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

Try / catch

try:
    out = model._process_batch(images, prompt)
except ValueError as e:
    if 'Unsupported numpy array shape' in str(e):
        images = [to_hwc(im) for im in images]
        out = model._process_batch(images, prompt)
    else:
        raise

Prevention

When it happens

Trigger: Passing a channels-first array from a torch/opencv preprocessing step, an (H,W,1) array from an expanded grayscale mask, or a 4-D stacked batch where a single image is expected.

Common situations: Feeding model-preprocessed tensors (CHW convention) directly instead of raw page rasters; using np.expand_dims on grayscale images; accidentally passing a batch ndarray instead of iterating its items.

Related errors


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