{"record":{"id":"92a3eda7b4d38604","repo":"invoke-ai/InvokeAI","slug":"degrade-sigma-must-broadcast-to-b-batch-size","errorCode":null,"errorMessage":"degrade_sigma must broadcast to [B={batch_size}], got shape {tuple(degrade_sigma_t.shape)}","messagePattern":"degrade_sigma must broadcast to \\[B=(.+?)\\], got shape (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/pid/decode.py","lineNumber":532,"sourceCode":"        # space at sr_scale * latent_spatial_down_factor times the latent.\n        total_up = self.sr_scale * self.latent_spatial_down_factor\n        img_h = int(latent.shape[-2] * total_up)\n        img_w = int(latent.shape[-1] * total_up)\n\n        gen = torch.Generator(device=device).manual_seed(int(cfg.seed))\n        noise = torch.randn(batch_size, 3, img_h, img_w, device=device, generator=gen, dtype=dtype)\n\n        sigma = cfg.degrade_sigma\n        if isinstance(sigma, Tensor):\n            degrade_sigma_t = sigma.to(device=device, dtype=torch.float32).reshape(-1)\n            if degrade_sigma_t.numel() == 1:\n                degrade_sigma_t = degrade_sigma_t.expand(batch_size).contiguous()\n        elif isinstance(sigma, (list, tuple)):\n            degrade_sigma_t = torch.tensor(sigma, device=device, dtype=torch.float32)\n        else:\n            degrade_sigma_t = torch.full((batch_size,), float(sigma), device=device, dtype=torch.float32)\n        if degrade_sigma_t.shape != (batch_size,):\n            raise ValueError(\n                f\"degrade_sigma must broadcast to [B={batch_size}], got shape {tuple(degrade_sigma_t.shape)}\"\n            )\n\n        caption_embs = caption_embs.to(device=device, dtype=dtype)\n        if caption_mask is not None:\n            caption_mask = caption_mask.to(device=device)\n        lq_latent = latent.to(device=device, dtype=dtype)\n\n        t_list = _get_t_list(device, num_steps=cfg.num_inference_steps)\n\n        if cfg.pid_memory_optimization:\n            # The setting is server-level and never reaches image metadata, so this log line is the\n            # only record that a decode ran optimized - and the only feedback the user gets that a\n            # yaml-only, restart-required knob took effect. It also reports whether chunking really\n            # engaged: below the chunk size the pixel blocks run unchunked and only the sampler-math\n            # change applies.\n            patch_tokens = batch_size * (img_h // self.net.patch_size) * (img_w // self.net.patch_size)\n            engaged = patch_tokens > _PID_ACTIVATION_CHUNK_SIZE","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/pid/decode.py#L514-L550","documentation":"decode() normalizes the degrade_sigma argument into a 1-D float32 tensor of length batch_size (scalar, sequence, or expandable tensor). If the resulting tensor's shape does not equal (batch_size,), it raises ValueError because the per-batch sigma schedule cannot be aligned with the latents.","triggerScenarios":"Calling decoder.decode(..., degrade_sigma=tensor_of_wrong_shape) where sigma has extra dims or a length different from the latent batch size, and it cannot be expanded to [B].","commonSituations":"Passing a per-image sigma list whose length differs from the latent batch; passing a 2-D tensor like [B,1] that torch.expand cannot squeeze to 1-D; copying sigma from a different batch size when reusing a batched call.","solutions":["Pass a scalar float for degrade_sigma so it fills a [B] tensor automatically","Pass a list/tuple or 1-D tensor with exactly batch_size elements","Ensure a tensor input is shape (batch_size,) or broadcastable via .expand(batch_size) before calling"],"exampleFix":"// before\ndecoder.decode(latent, caption_embs, degrade_sigma=torch.randn(4, 1))\n// after\ndecoder.decode(latent, caption_embs, degrade_sigma=torch.full((4,), 0.5))","handlingStrategy":"validation","validationCode":"b = latent.shape[0]\nif isinstance(degrade_sigma, torch.Tensor):\n    degrade_sigma = degrade_sigma.reshape(-1)\n    assert degrade_sigma.numel() == 1 or degrade_sigma.numel() == b, \"sigma must be scalar or length B\"\ndecoder.decode(latent=latent, caption_embs=embs, degrade_sigma=degrade_sigma)","typeGuard":"def sigma_broadcasts(sigma, batch_size: int) -> bool:\n    if isinstance(sigma, (int, float)):\n        return True\n    if isinstance(sigma, (list, tuple)):\n        return len(sigma) == batch_size\n    if isinstance(sigma, torch.Tensor):\n        return sigma.numel() in (1, batch_size)\n    return False","tryCatchPattern":"try:\n    image = decoder.decode(latent=lat, caption_embs=embs, degrade_sigma=sigma)\nexcept ValueError as e:\n    logger.error(str(e)); image = None","preventionTips":["Prefer scalar floats for degrade_sigma unless per-sample control is needed","Keep sigma list length tied to latent.shape[0] in the same code path","Flatten sigma tensors to 1-D before calling decode"],"tags":["valueerror","shape-mismatch","tensor"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}