docling-project/docling · error · ValueError
Unsupported numpy array shape: {image.shape}
Error message
Unsupported numpy array shape: {image.shape} What it means
Same raster contract as the other engines, enforced per image inside the MLX loop: numpy inputs must be (H,W), (H,W,3) or (H,W,4); anything else (CHW tensors, (H,W,1), 4-D) raises ValueError with the shape. Conversion happens under the global MLX lock, so the error surfaces mid-batch.
Source
Thrown at docling/models/vlm_pipeline_models/mlx_model.py:223
# MLX models are not thread-safe - use global lock to serialize access
with _MLX_GLOBAL_LOCK:
_log.debug("MLX model: Acquired global lock for thread safety")
for image, user_prompt in zip(image_list, user_prompts):
# Convert numpy array to PIL Image if needed
if isinstance(image, np.ndarray):
if image.ndim == 3 and image.shape[2] in [3, 4]:
# RGB or RGBA array
from PIL import Image as PILImage
image = PILImage.fromarray(image.astype(np.uint8))
elif image.ndim == 2:
# Grayscale array
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 (handles RGBA, L, etc.)
if image.mode != "RGB":
image = image.convert("RGB")
# Use the MLX chat template approach like in the __call__ method
formatted_prompt = self.apply_chat_template(
self.processor, self.config, user_prompt, num_images=1
)
# Stream generate with stop strings and custom stopping criteria support
start_time = time.time()
_log.debug("start generating ...")
tokens: list[VlmPredictionToken] = []
output = ""View on GitHub (pinned to 61d76f1ff3)
Solutions
- Transpose CHW to HWC before the call
- Squeeze (H,W,1) down to (H,W) for the grayscale branch
- Pass PIL/docling Image objects to bypass numpy conversion entirely
Example fix
# before model.process_images([chw_array], "describe") # (3,H,W) -> ValueError # after model.process_images([chw_array.transpose(1, 2, 0)], "describe")
Defensive patterns
Strategy: type-guard
Validate before calling
import numpy as np
def normalize_raster(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]
if a.ndim not in (2, 3) or (a.ndim == 3 and a.shape[2] not in (3, 4)):
raise ValueError(f'cannot normalize shape {a.shape}')
return a.astype(np.uint8) Type guard
import numpy as np
def is_supported_mlx_raster(a: np.ndarray) -> bool:
return a.ndim == 2 or (a.ndim == 3 and a.shape[2] in (3, 4)) Try / catch
try:
model.process_images(images, prompt)
except ValueError as e:
if 'Unsupported numpy array shape' in str(e):
images = [normalize_raster(im) for im in images]
model.process_images(images, prompt)
else:
raise Prevention
- Convert CHW tensors to HWC before crossing into Docling
- Squeeze singleton channel axes on masks and grayscale sources
- Prefer PIL Image inputs on macOS pipelines
When it happens
Trigger: Passing a channels-first (3,H,W) array, an (H,W,1) grayscale mask, or a 4-D batch ndarray as an element of image_batch to the MLX model.
Common situations: macOS preprocessing that keeps torch's CHW layout; grayscale masks with an explicit 1-channel axis; passing a stacked batch ndarray where one image is expected.
Related errors
- Unsupported numpy array shape: {image.shape}
- Unsupported numpy array shape: {img.shape}
- Unsupported numpy array shape: {image.shape}
- Incompatible file format {self.input_format} was passed to I
- Could not load image for document {self.file}
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/cb36ba972db9e8d8.
Report an issue: GitHub.