{"record":{"id":"a6a1a31c82e4ca1e","repo":"AUTOMATIC1111/stable-diffusion-webui","slug":"tensor-shape-does-not-describe-a-bchw-tensor","errorCode":null,"errorMessage":"{tensor.shape} does not describe a BCHW tensor","messagePattern":"(.+?) does not describe a BCHW tensor","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"modules/upscaler_utils.py","lineNumber":27,"sourceCode":"from modules import devices, images, shared, torch_utils\n\nlogger = logging.getLogger(__name__)\n\n\ndef pil_image_to_torch_bgr(img: Image.Image) -> torch.Tensor:\n    img = np.array(img.convert(\"RGB\"))\n    img = img[:, :, ::-1]  # flip RGB to BGR\n    img = np.transpose(img, (2, 0, 1))  # HWC to CHW\n    img = np.ascontiguousarray(img) / 255  # Rescale to [0, 1]\n    return torch.from_numpy(img)\n\n\ndef torch_bgr_to_pil_image(tensor: torch.Tensor) -> Image.Image:\n    if tensor.ndim == 4:\n        # If we're given a tensor with a batch dimension, squeeze it out\n        # (but only if it's a batch of size 1).\n        if tensor.shape[0] != 1:\n            raise ValueError(f\"{tensor.shape} does not describe a BCHW tensor\")\n        tensor = tensor.squeeze(0)\n    assert tensor.ndim == 3, f\"{tensor.shape} does not describe a CHW tensor\"\n    # TODO: is `tensor.float().cpu()...numpy()` the most efficient idiom?\n    arr = tensor.float().cpu().clamp_(0, 1).numpy()  # clamp\n    arr = 255.0 * np.moveaxis(arr, 0, 2)  # CHW to HWC, rescale\n    arr = arr.round().astype(np.uint8)\n    arr = arr[:, :, ::-1]  # flip BGR to RGB\n    return Image.fromarray(arr, \"RGB\")\n\n\ndef upscale_pil_patch(model, img: Image.Image) -> Image.Image:\n    \"\"\"\n    Upscale a given PIL image using the given model.\n    \"\"\"\n    param = torch_utils.get_param(model)\n\n    with torch.inference_mode():\n        tensor = pil_image_to_torch_bgr(img).unsqueeze(0)  # add batch dimension","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/82a973c04367123ae98bd9abdf80d9eda9b910e2/modules/upscaler_utils.py#L9-L45","documentation":"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.","triggerScenarios":"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.","commonSituations":"Extensions batch-processing multiple images through single-image upscaler utilities; code migrated from img2img batching where tensors naturally carry a real batch dimension.","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"],"exampleFix":"# before\nimg = torch_bgr_to_pil_image(batched_bchw)  # batch=4 -> ValueError\n# after\nimages = [torch_bgr_to_pil_image(t) for t in batched_bchw]","handlingStrategy":"type-guard","validationCode":"import torch\ndef to_bchw_of_one(t: torch.Tensor) -> torch.Tensor:\n    if t.ndim == 3:\n        return t.unsqueeze(0)\n    if t.ndim == 4 and t.shape[0] == 1:\n        return t\n    raise ValueError(f'{t.shape} is not CHW or B1HW')","typeGuard":"def is_single_image_tensor(t: torch.Tensor) -> bool:\n    return t.ndim == 3 or (t.ndim == 4 and t.shape[0] == 1)","tryCatchPattern":null,"preventionTips":["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"],"tags":["upscaling","tensor","image-processing","batch","validation"],"backgroundTag":null,"analyzedSha":"82a973c04367123ae98bd9abdf80d9eda9b910e2","analyzedAt":"2026-08-14T16:46:43.225Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}