roboflow/supervision · error · ValueError
Panoptic PNG masks must have at least 3 channels.
Error message
Panoptic PNG masks must have at least 3 channels.
What it means
Raised when decoding a panoptic-segmentation PNG whose decoded array has 3 dimensions but fewer than 3 channels in the last axis. Panoptic IDs are RGB-encoded as little-endian 24-bit integers (R + G<<8 + B<<16), so at least R, G, and B channels must exist; a 1- or 2-channel PNG (grayscale with an extra axis, or LA alpha-only layouts) cannot carry the encoding. Pure 2-D grayscale masks are handled earlier and returned as-is.
Source
Thrown at src/supervision/detection/tools/transformers.py:229
def png_string_to_segmentation_array(png_string: bytes) -> npt.NDArray[Any]:
"""
Convert a PNG byte string to a panoptic segmentation array.
Args:
png_string: A byte string representing the PNG image.
Returns:
A segmentation ID array with shape (H, W), where each unique value
represents a different object or category. RGB-encoded panoptic
PNGs are decoded as little-endian 24-bit integers; alpha is ignored.
"""
image = Image.open(io.BytesIO(png_string))
mask = np.array(image, dtype=np.uint8)
if mask.ndim == 2:
return mask.astype(np.uint32)
if mask.shape[2] < 3:
raise ValueError("Panoptic PNG masks must have at least 3 channels.")
segmentation = (
mask[:, :, 0].astype(np.uint32)
+ (mask[:, :, 1].astype(np.uint32) << 8)
+ (mask[:, :, 2].astype(np.uint32) << 16)
)
return cast(npt.NDArray[Any], segmentation)
def append_class_names_to_data(
class_ids: npt.NDArray[Any],
id2label: dict[int, str] | None,
data: dict[str, Any] | None = None,
) -> dict[str, Any]:
"""
Helper function to create or append to a data dictionary with class names if
available.
View on GitHub (pinned to 7f254d9784)
Solutions
- Regenerate or re-save the PNG in RGB mode: Image.open(p).convert('RGB').save(p) before passing the bytes.
- If the mask is genuinely class-ID grayscale, pass a 2-D single-channel PNG so it takes the grayscale path instead.
- Check the producer of png_string — it should emit the original model panoptic PNG unmodified.
Example fix
# before
png_bytes = open('panoptic_la.png', 'rb').read()
segmentation = decode_png_string(png_bytes) # ValueError
# after
from PIL import Image
img = Image.open('panoptic_la.png').convert('RGB')
import io
buf = io.BytesIO(); img.save(buf, format='PNG')
segmentation = decode_png_string(buf.getvalue()) Defensive patterns
Strategy: validation
Validate before calling
import io
import numpy as np
from PIL import Image
def load_panoptic_png(png_bytes: bytes) -> np.ndarray:
img = Image.open(io.BytesIO(png_bytes))
if img.mode not in ('RGB', 'L'):
img = img.convert('RGB')
return np.array(img)
segmentation = decode_png_string(png_bytes) if is_valid_panoptic_png(png_bytes) else ... Type guard
def is_valid_panoptic_png(png_bytes: bytes) -> bool:
import io
from PIL import Image
arr = np.array(Image.open(io.BytesIO(png_bytes)))
return arr.ndim == 2 or arr.shape[2] >= 3 Try / catch
try:
segmentation = decode_png_string(png_bytes)
except ValueError as err:
if 'at least 3 channels' in str(err):
img = Image.open(io.BytesIO(png_bytes)).convert('RGB')
buf = io.BytesIO(); img.save(buf, format='PNG')
segmentation = decode_png_string(buf.getvalue())
else:
raise Prevention
- Pass model-produced panoptic PNGs through unmodified.
- Normalize image mode to RGB (or L for class-ID maps) in your data-loading layer.
When it happens
Trigger: Calling the panoptic-PNG decoder (used by Transformers connectors, e.g. for Mask2Former/MaskFormer post-processing) with an LA-mode (luminance+alpha) PNG or another 2-channel image saved by an upstream tool.
Common situations: A model or preprocessing step converts the panoptic PNG to grayscale-with-alpha before it reaches supervision; corrupted or re-encoded PNG files from a dataset pipeline; version changes in an upstream library that alters the saved PNG mode.
Related errors
- module {__name__} has no attribute {name}
- Edge indices must use the 1-based convention and be within t
- sigma must contain at least one value
- All sigma values must be positive
- max_axis must be positive when provided
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/c176652e331316d5.
Report an issue: GitHub.