roboflow/supervision · error · TypeError

Unsupported image type: {type(image)}

Error message

Unsupported image type: {type(image)}

What it means

Raised by the ensure_cv2_image_for_function decorator's wrapper in supervision.utils.conversion when the first `image` argument of a decorated standalone image-processing function is neither np.ndarray nor PIL.Image.Image. The decorator converts PIL to BGR array, runs the function, and converts back; unsupported types fail fast with this TypeError.

Source

Thrown at src/supervision/utils/conversion.py:80

    np.ndarray, converts back when processing is complete.

    Assumes the annotators do NOT modify the scene in-place.

    Raises:
        TypeError: If `image` is not a `numpy.ndarray` or `PIL.Image.Image`.
    """

    @functools.wraps(image_processing_fun)
    def wrapper(image: ImageType, *args: Any, **kwargs: Any) -> Any:
        if isinstance(image, np.ndarray):
            return image_processing_fun(image, *args, **kwargs)

        if isinstance(image, Image.Image):
            scene = pillow_to_cv2(image)
            annotated = image_processing_fun(scene, *args, **kwargs)
            return cv2_to_pillow(annotated)

        raise TypeError(f"Unsupported image type: {type(image)}")

    return cast(F, wrapper)


def ensure_pil_image_for_class_method(
    annotate_func: F,
) -> F:
    """
    Decorates image processing functions that accept np.ndarray, converting `image` to
    PIL image, converts back when processing is complete.

    Assumes the annotators modify the scene in-place.

    Raises:
        TypeError: If `scene` is not a `numpy.ndarray` or `PIL.Image.Image`.
    """

    @functools.wraps(annotate_func)

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Decode bytes to an array first: np.frombuffer(data, np.uint8) then cv2.imdecode(..., cv2.IMREAD_COLOR).
  2. Convert tensors: image = tensor.detach().cpu().numpy().
  3. Load paths with cv2.imread(str(path)) before calling the function.
  4. Verify the argument order — the first positional arg must be the image itself.

Example fix

// before
result = draw_helper(image_bytes, detections)  # TypeError

// after
buf = np.frombuffer(image_bytes, np.uint8)
image = cv2.imdecode(buf, cv2.IMREAD_COLOR)
result = draw_helper(image, detections)
Defensive patterns

Strategy: type-guard

Validate before calling

def to_ndarray_if_needed(image: object) -> np.ndarray | Image.Image:
    if isinstance(image, (np.ndarray, Image.Image)):
        return image
    if hasattr(image, 'detach'):
        return image.detach().cpu().numpy()
    raise TypeError(f'Cannot use {type(image)} as an image')

Type guard

def is_supported_image(image: object) -> TypeGuard[Union[np.ndarray, Image.Image]]:
    return isinstance(image, (np.ndarray, Image.Image))

Try / catch

try:
    result = decorated_fn(image, ...)
except TypeError as e:
    if 'Unsupported image type' in str(e):
        image = np.asarray(decode_anyhow(image))
        result = decorated_fn(image, ...)
    else:
        raise

Prevention

When it happens

Trigger: Calling a decorated module-level function (not a bound method) such as a drawing/utility helper with a torch.Tensor, path string, bytes buffer, or None as the first positional argument.

Common situations: Sending raw HTTP image bytes or a base64 string instead of a decoded array; passing a tensor from a deep-learning pipeline; passing a cv2.VideoCapture capture flag or a Path object.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/b57cb7bdfc37d4d3. Report an issue: GitHub.