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.

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.

Appendix: 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)