{"record":{"id":"9b5d6347c09a8863","repo":"docling-project/docling","slug":"unsupported-numpy-array-shape-img-shape","errorCode":null,"errorMessage":"Unsupported numpy array shape: {img.shape}","messagePattern":"Unsupported numpy array shape: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/models/extraction/nuextract_transformers_model.py","lineNumber":194,"sourceCode":"        Args:\n            image_batch: Iterable of PIL Images or numpy arrays\n            prompt: Either:\n                - str: Single template used for all images\n                - list[str]: List of templates (one per image, must match image count)\n        \"\"\"\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 templates (1 per image)\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 templates ({len(prompt)}) must match number of images ({len(pil_images)})\"\n                )\n            templates = prompt","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/models/extraction/nuextract_transformers_model.py#L176-L212","documentation":"ValueError from image normalization in NuExtractTransformersModel: a numpy image in the batch must be 2-D grayscale (H x W) or 3-D with 3 or 4 channels (H x W x 3/4). Any other shape (e.g. H x W x 1, or higher-dimensional arrays) is rejected because PIL cannot interpret it as an image.","triggerScenarios":"Passing image_batch entries as numpy arrays with img.ndim not in {2} and not (ndim==3 and shape[2] in (3,4)); typical offenders are (H, W, 1) arrays from grayscale pipelines or float arrays with unexpected trailing dimensions.","commonSituations":"Feeding model-preprocessed tensors or grayscale arrays saved with a singleton channel dimension; images coming from a different preprocessing stage that kept channels-first (C, H, W) layout.","solutions":["Squeeze singleton channels: img = img.squeeze(-1) for (H, W, 1) arrays so they become 2-D.","Convert channels-first arrays: img = img.transpose(1, 2, 0) before passing.","Pass PIL Images directly instead of numpy arrays to sidestep shape interpretation."],"exampleFix":"# before\nimage_batch = [gray_hwc1_array]  # shape (H, W, 1) -> ValueError\n\n# after\nimage_batch = [img.squeeze(-1) if img.ndim == 3 and img.shape[2] == 1 else img\n                for img in image_batch]\n# or pass PIL images: image_batch = [Image.fromarray(arr)]","handlingStrategy":"validation","validationCode":"def valid_image_shape(img: 'np.ndarray') -> bool:\n    return img.ndim == 2 or (img.ndim == 3 and img.shape[2] in (3, 4))\nassert all(valid_image_shape(i) for i in image_batch if isinstance(i, np.ndarray))","typeGuard":"def is_hwc_array(img) -> bool:\n    return isinstance(img, np.ndarray) and (img.ndim == 2 or (img.ndim == 3 and img.shape[2] in (3, 4)))","tryCatchPattern":"try:\n    preds = model(image_batch, prompt)\nexcept ValueError as e:\n    if 'Unsupported numpy array shape' in str(e):\n        image_batch = [np.squeeze(i) if isinstance(i, np.ndarray) and i.ndim == 3 and i.shape[2] == 1 else i for i in image_batch]\n        preds = model(image_batch, prompt)","preventionTips":["Normalize every numpy image to HxW or HxWx3 before batching.","Prefer passing PIL Images to sidestep shape ambiguity."],"tags":["nuextract","numpy","image-processing","extraction"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}