AUTOMATIC1111/stable-diffusion-webui · error · ValueError
{tensor.shape} does not describe a BCHW tensor
Error message
{tensor.shape} does not describe a BCHW tensor What it means
upscaler_utils.torch_bgr_to_pil_image() accepts a CHW tensor or a 4D tensor only when the batch dimension is exactly 1 (which it squeezes out). A 4D tensor with shape[0] != 1 cannot be unambiguously converted to a single PIL image, so it is rejected with this ValueError before the numpy conversion.
Source
Thrown at modules/upscaler_utils.py:27
from modules import devices, images, shared, torch_utils
logger = logging.getLogger(__name__)
def pil_image_to_torch_bgr(img: Image.Image) -> torch.Tensor:
img = np.array(img.convert("RGB"))
img = img[:, :, ::-1] # flip RGB to BGR
img = np.transpose(img, (2, 0, 1)) # HWC to CHW
img = np.ascontiguousarray(img) / 255 # Rescale to [0, 1]
return torch.from_numpy(img)
def torch_bgr_to_pil_image(tensor: torch.Tensor) -> Image.Image:
if tensor.ndim == 4:
# If we're given a tensor with a batch dimension, squeeze it out
# (but only if it's a batch of size 1).
if tensor.shape[0] != 1:
raise ValueError(f"{tensor.shape} does not describe a BCHW tensor")
tensor = tensor.squeeze(0)
assert tensor.ndim == 3, f"{tensor.shape} does not describe a CHW tensor"
# TODO: is `tensor.float().cpu()...numpy()` the most efficient idiom?
arr = tensor.float().cpu().clamp_(0, 1).numpy() # clamp
arr = 255.0 * np.moveaxis(arr, 0, 2) # CHW to HWC, rescale
arr = arr.round().astype(np.uint8)
arr = arr[:, :, ::-1] # flip BGR to RGB
return Image.fromarray(arr, "RGB")
def upscale_pil_patch(model, img: Image.Image) -> Image.Image:
"""
Upscale a given PIL image using the given model.
"""
param = torch_utils.get_param(model)
with torch.inference_mode():
tensor = pil_image_to_torch_bgr(img).unsqueeze(0) # add batch dimensionView on GitHub (pinned to 82a973c043)
Solutions
- Iterate the batch and convert each image: for img in tensor: pil = torch_bgr_to_pil_image(img)
- Or select/slice one image first: torch_bgr_to_pil_image(tensor[i])
- If you authored the tensor, build it as CHW/B1HW from the start via pil_image_to_bgr_image
Example fix
# before img = torch_bgr_to_pil_image(batched_bchw) # batch=4 -> ValueError # after images = [torch_bgr_to_pil_image(t) for t in batched_bchw]
Defensive patterns
Strategy: type-guard
Validate before calling
import torch
def to_bchw_of_one(t: torch.Tensor) -> torch.Tensor:
if t.ndim == 3:
return t.unsqueeze(0)
if t.ndim == 4 and t.shape[0] == 1:
return t
raise ValueError(f'{t.shape} is not CHW or B1HW') Type guard
def is_single_image_tensor(t: torch.Tensor) -> bool:
return t.ndim == 3 or (t.ndim == 4 and t.shape[0] == 1) Prevention
- Loop over the batch dimension before calling single-image converters
- Keep a utility that squeezes/selects a single sample before conversion
- Unit-test tensor plumbing with batch sizes 1 and >1
When it happens
Trigger: Passing a Bx3xHxW BGR tensor with batch size 2+ into an upscaler path (e.g. custom upscale code or an extension calling upscale_with_model helpers that round-trip through torch_bgr_to_pil_image), instead of looping over the batch.
Common situations: Extensions batch-processing multiple images through single-image upscaler utilities; code migrated from img2img batching where tensors naturally carry a real batch dimension.
Related errors
- Received a different number of prompts ({len(self.all_prompt
- bad number of images passed: {len(imgs)}; expecting {self.ba
- Sampler not found
- Invalid encoded image
- always on script {alwayson_script_name} not found
AI-assisted analysis of AUTOMATIC1111/stable-diffusion-webui@82a973c043 (2026-08-14).
Data as JSON: /api/errors/a6a1a31c82e4ca1e.
Report an issue: GitHub.