invoke-ai/InvokeAI · error · ValueError

Decoded frame must be RGB; got shape {frame.shape}

Error message

Decoded frame must be RGB; got shape {frame.shape}

What it means

_validate_decoded_frame checks that a decoded video frame is a 3-dimensional RGB ndarray (H, W, 3). OpenCV decodes frames as BGR with shape (H, W, 3), but frames arriving here are expected to have been converted to RGB; a grayscale, RGBA, or non-array frame fails this check. It is a defensive invariant check on the decode pipeline.

Source

Thrown at invokeai/app/util/video_decode_worker.py:71

    if sys.platform != "linux":
        return
    try:
        import os
        import resource

        pages = int(Path("/proc/self/statm").read_text().split()[0])
        limit = pages * os.sysconf("SC_PAGE_SIZE") + WORKER_MEMORY_HEADROOM_BYTES
        _soft, hard = resource.getrlimit(resource.RLIMIT_AS)
        if hard != resource.RLIM_INFINITY:
            limit = min(limit, hard)
        resource.setrlimit(resource.RLIMIT_AS, (limit, hard))
    except (OSError, ValueError):
        pass


def _validate_decoded_frame(frame: np.ndarray) -> None:
    if frame.ndim != 3 or frame.shape[2] != 3:
        raise ValueError(f"Decoded frame must be RGB; got shape {frame.shape}")
    height, width = frame.shape[:2]
    if height <= 0 or width <= 0 or height * width > MAX_FRAME_PIXELS:
        raise ValueError(f"Decoded frame dimensions {width}x{height} exceed the maximum decodable size")


def _assert_decodable_dims(video_path: Path) -> None:
    """Refuses to decode frames from a video whose reported dimensions exceed the bound.

    If the dimensions cannot be probed, decoding is refused because the parent's frame
    record bound and PIL checks run only after the decoder has allocated the frame.
    """
    try:
        width, height, _duration, _fps = _probe(video_path)[:4]
    except Exception as error:
        raise ValueError(f"Unable to validate video dimensions for {video_path}") from error
    if width <= 0 or height <= 0:
        raise ValueError(f"Video reports invalid dimensions {width}x{height}")
    if width * height > MAX_FRAME_PIXELS:

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Convert BGR frames to RGB with cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) before validating
  2. For grayscale videos, stack or cv2.cvtColor(cv2.COLOR_GRAY2RGB) before passing the frame
  3. Check the decoder path producing the frame and ensure it always yields (H, W, 3) uint8 RGB arrays

Example fix

// before
_validate_decoded_frame(frame_bgr)

// after
frame_rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)
_validate_decoded_frame(frame_rgb)
Defensive patterns

Strategy: validation

Validate before calling

def is_rgb_frame(f) -> bool:
    return isinstance(f, np.ndarray) and f.ndim == 3 and f.shape[2] == 3

Type guard

def is_rgb_frame(f: object) -> bool:
    return isinstance(f, np.ndarray) and f.ndim == 3 and f.shape[2] == 3

Try / catch

try:
    _validate_decoded_frame(frame)
except ValueError as e:
    if "must be RGB" in str(e):
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        _validate_decoded_frame(frame)
    else:
        raise

Prevention

When it happens

Trigger: A decoder returns a grayscale frame (ndim==2), an RGBA frame (shape[2]==4), or a non-RGB array passed to _validate_decoded_frame without cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) conversion.

Common situations: Forgetting cv2.COLOR_BGR2RGB conversion when switching between cv2 and imageio/PIL paths; videos with alpha channels or grayscale codecs; a decoder returning None or a differently-shaped array due to codec quirks.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/060d4118885f5031. Report an issue: GitHub.