invoke-ai/InvokeAI · error · ValueError

color_tensor must be a 3xHxW tensor

Error message

color_tensor must be a 3xHxW tensor

What it means

_require_color_tensor guards every color-space conversion helper: input must be a 3-D tensor with 3 channels in the first dimension (3xHxW, CHW RGB layout). Any other rank or channel layout is rejected before matrix math is applied.

Source

Thrown at invokeai/backend/image_util/color_conversion.py:56

    (0.2104542553, 0.7936177850, -0.0040720468),
    (1.9779984951, -2.4285922050, 0.4505937099),
    (0.0259040371, 0.7827717662, -0.8086757660),
)
_OKLAB_TO_LMS_CUBE_ROOT_MATRIX = (
    (1.0, 0.3963377774, 0.2158037573),
    (1.0, -0.1055613458, -0.0638541728),
    (1.0, -0.0894841775, -1.2914855480),
)
_LMS_TO_LINEAR_SRGB_MATRIX = (
    (4.0767416621, -3.3077115913, 0.2309699292),
    (-1.2684380046, 2.6097574011, -0.3413193965),
    (-0.0041960863, -0.7034186147, 1.7076147010),
)


def _require_color_tensor(color_tensor: torch.Tensor) -> torch.Tensor:
    if color_tensor.ndim != 3 or color_tensor.shape[0] != 3:
        raise ValueError("color_tensor must be a 3xHxW tensor")
    return color_tensor


def _require_reference_illuminant(reference_illuminant: str) -> str:
    normalized = reference_illuminant.upper()
    if normalized not in _REFERENCE_ILLUMINANTS:
        raise ValueError(f"Unsupported reference_illuminant: {reference_illuminant}")
    return normalized


def _full_like_spatial(reference_tensor: torch.Tensor, fill_value: float) -> torch.Tensor:
    return torch.full(
        reference_tensor.shape[1:], fill_value, dtype=reference_tensor.dtype, device=reference_tensor.device
    )


def _degrees_from_unit_hue(unit_hue_tensor: torch.Tensor) -> torch.Tensor:
    return torch.remainder(unit_hue_tensor * 360.0, 360.0)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Convert to CHW with tensor.permute(2, 0, 1) for HWC inputs
  2. Slice RGB: tensor[:3] for RGBA, or tensor[None] for HxW grayscale
  3. Squeeze/select the batch: tensor[0] for a 1-element BCHW batch
  4. Validate shape before calling: assert t.ndim == 3 and t.shape[0] == 3

Example fix

// before
srgb_from_linear_srgb(image_np_tensor)  # HWC
// after
chw = torch.from_numpy(image).permute(2, 0, 1)[:3]
srgb_from_linear_srgb(chw)
Defensive patterns

Strategy: type-guard

Validate before calling

if tensor.ndim != 3 or tensor.shape[0] != 3:
    tensor = tensor.permute(2, 0, 1)[:3]  # HWC/RGBA -> CHW RGB

Type guard

def is_3xhxw(t: torch.Tensor) -> bool:
    return isinstance(t, torch.Tensor) and t.ndim == 3 and t.shape[0] == 3

Try / catch

try:
    out = srgb_from_linear_srgb(tensor)
except ValueError as e:
    if "3xHxW" in str(e):
        tensor = tensor.permute(2, 0, 1)[:3]
        out = srgb_from_linear_srgb(tensor)
    else:
        raise

Prevention

When it happens

Trigger: Passing an HWC tensor (shape HxWx3), a batched BCHW tensor, a grayscale 1xHxW or HxW tensor, or a 4-channel RGBA tensor into helpers like srgb_from_linear_srgb or xyz_from_srgb.

Common situations: Forgetting to permute a PIL/numpy image (HWC) to CHW, passing a batch dimension, loading RGBA images, working with grayscale images.

Understand the failure class

Background: Tensor shape mismatch errors ("must have shape", "expected shape ... got ..."): when tensor dimensions disagree with what an op or layer was told to expect — this error's family across 6 libraries.

Related errors


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