invoke-ai/InvokeAI · error · ValueError
Invalid number of channels.
Error message
Invalid number of channels.
What it means
normalize_image_channel_count converts numpy image arrays to 3 channels: 1-channel is triplicated, 4-channel RGBA is alpha-blended onto white, 3-channel passes through. It raises this ValueError only if channels is not in {1,3,4} — e.g. a 2-channel or >4-channel array slipped past the caller. Note the code asserts channels in {1,3,4} just above, so hitting the raise usually means a build with -O0/asserts stripped or a shape confusion.
Source
Thrown at invokeai/backend/image_util/util.py:137
"""
assert image.dtype == np.uint8
if image.ndim == 2:
image = image[:, :, None]
assert image.ndim == 3
_height, _width, channels = image.shape
assert channels == 1 or channels == 3 or channels == 4
if channels == 3:
return image
if channels == 1:
return np.concatenate([image, image, image], axis=2)
if channels == 4:
color = image[:, :, 0:3].astype(np.float32)
alpha = image[:, :, 3:4].astype(np.float32) / 255.0
normalized = color * alpha + 255.0 * (1.0 - alpha)
normalized = normalized.clip(0, 255).astype(np.uint8)
return normalized
raise ValueError("Invalid number of channels.")
def resize_image_to_resolution(input_image: np.ndarray, resolution: int) -> np.ndarray:
"""Resizes an image, fitting it to the given resolution.
Adapted from https://github.com/huggingface/controlnet_aux (Apache-2.0 license).
Args:
input_image: The input image.
resolution: The resolution to fit the image to.
Returns:
The resized image.
"""
h = float(input_image.shape[0])
w = float(input_image.shape[1])
scaling_factor = float(resolution) / min(h, w)
h = int(h * scaling_factor)View on GitHub (pinned to 0b6a024f2f)
Solutions
- Convert the input to RGB or grayscale before calling: img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) or load with cv2.IMREAD_COLOR.
- Check image.shape — if the last dimension is not 1, 3, or 4, reshape or drop the extra channels before calling.
- If the array is (H,W,2), inspect the pipeline step that produced it; usually one channel is data and one is alpha — split or merge them appropriately.
Example fix
// before edges = get_canny_edges(odd_array) # odd_array.shape == (H, W, 2) // after assert odd_array.ndim == 3 and odd_array.shape[2] in (1, 3, 4) rgb = cv2.cvtColor(odd_array, cv2.COLOR_BGR2RGB) if odd_array.shape[2] == 3 else odd_array[:, :, :3] edges = get_canny_edges(rgb)
Defensive patterns
Strategy: type-guard
Validate before calling
def ensure_rgb_uint8(img: np.ndarray) -> np.ndarray:
assert img.dtype == np.uint8
if img.ndim == 2:
img = img[:, :, None]
if img.shape[2] not in (1, 3, 4):
raise ValueError(f"expected 1/3/4 channels, got {img.shape[2]}")
return img Type guard
def is_normalizable_image(img: np.ndarray) -> bool:
return img.dtype == np.uint8 and img.ndim == 3 and img.shape[2] in (1, 3, 4) Try / catch
try:
normalized = normalize_image_channel_count(img)
except ValueError:
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # or inspect img.shape and fix channels
normalized = normalize_image_channel_count(img) Prevention
- Log/inspect img.shape before preprocessing; expect (H, W, 3) for typical RGB sources.
- Avoid cv2.IMREAD_UNCHANGED unless you handle alpha/16-bit layouts yourself.
- Convert all inputs to RGB uint8 at the ingestion boundary of your pipeline, once.
When it happens
Trigger: Passing a numpy array with 2 channels (e.g. cv2 grayscale loaded with an odd flag or a (H,W,2) array), 5+ channels, or an accidental shape mismatch such as stacking two single-channel images. Called via np_img_resize, get_canny_edges, and controlnet run paths.
Common situations: Feeding video frames or exotic formats (e.g. YUV, 16-bit multi-channel) into controlnet preprocessing, concatenating arrays incorrectly, or an OpenCV load returning an unexpected channel layout (IMREAD_UNCHANGED on a 2-channel PNG).
Related errors
- Decoded frame dimensions {width}x{height} exceed the maximum
- y_min ({self.y_min}) is greater than y_max ({self.y_max}).
- Not authorized to modify this image
- Image not found
- Not authorized to access this image
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/1796c1ad5623d5c3.
Report an issue: GitHub.