huggingface/transformers · error · ValueError

Invalid image type: {type(img)}

Error message

Invalid image type: {type(img)}

What it means

Raised by `transformers.image_utils.to_numpy_array` when its argument fails `is_valid_image` — i.e. it is not a PIL.Image.Image, numpy.ndarray, or torch.Tensor. This function is the standard bridge used inside image processors to convert any supported image input to np.ndarray, and it deliberately refuses anything it would have to guess how to convert. The error names the offending type to make the mismatch obvious.

Source

Thrown at src/transformers/image_utils.py:281

    if isinstance(images, (list, tuple)) and is_valid_list_of_images(images):
        if is_pil_image(images[0]) or images[0].ndim == expected_ndims:
            return [images]
        if images[0].ndim == expected_ndims + 1:
            return [list(image) for image in images]

    # If it's a single image, convert it to a list of lists
    if is_valid_image(images):
        if is_pil_image(images) or images.ndim == expected_ndims:
            return [[images]]
        if images.ndim == expected_ndims + 1:
            return [list(images)]

    raise ValueError("Invalid input type. Must be a single image, a list of images, or a list of batches of images.")


def to_numpy_array(img) -> np.ndarray:
    if not is_valid_image(img):
        raise ValueError(f"Invalid image type: {type(img)}")

    if is_vision_available() and isinstance(img, PIL.Image.Image):
        return np.array(img)
    return to_numpy(img)


def infer_channel_dimension_format(
    image: np.ndarray, num_channels: int | tuple[int, ...] | None = None
) -> ChannelDimension:
    """
    Infers the channel dimension format of `image`.

    Args:
        image (`np.ndarray`):
            The image to infer the channel dimension of.
        num_channels (`int` or `tuple[int, ...]`, *optional*, defaults to `(1, 3)`):
            The number of channels of the image.

View on GitHub (pinned to a597f97485)

Solutions

  1. Convert first: `np.asarray(x)` for lists/tf tensors, `x.numpy()` for tf eager tensors.
  2. For paths/URLs/base64 strings, use `load_image(image)` which returns a PIL image.
  3. Guard upstream code against None before calling conversion helpers.

Example fix

// before
arr = to_numpy_array("/data/cat.jpg")   # ValueError
arr = to_numpy_array(tf_tensor)         # ValueError

// after
from transformers.image_utils import load_image
arr = to_numpy_array(load_image("/data/cat.jpg"))
arr = to_numpy_array(tf_tensor.numpy())
Defensive patterns

Strategy: type-guard

Type guard

from transformers.image_utils import is_valid_image

def is_convertible_image(x) -> bool:
    return is_valid_image(x)

Prevention

When it happens

Trigger: Calling `to_numpy_array()` (or a processor path that uses it) with a TensorFlow tensor, a plain list, a string path/URL, bytes, or None. Note the string branch of the message is misleading: paths must be loaded with `load_image` first.

Common situations: Feeding tf.Tensor from a TF/Keras pipeline into a transformers image processor; passing raw nested lists built from pixel data instead of an ndarray; a None slipping through from a failed upstream load.

Related errors


AI-assisted analysis of huggingface/transformers@a597f97485 (2026-08-14). Data as JSON: /api/errors/ed1532c60cbaf23d. Report an issue: GitHub.