Comfy-Org/ComfyUI · error · ValueError

SeedVR2 expected {name} channels to be {channels}, got shape

Error message

SeedVR2 expected {name} channels to be {channels}, got shape {tuple(x.shape)}.

What it means

The companion check to the 5-D guard: SeedVR2 requires exactly the expected channel count on the video latent axis 1 (SEEDVR2_LATENT_CHANNELS for the noisy latent, that +1 for the conditioning latent which carries an extra mask channel). A different channel count means the wrong VAE or wrong tensor was supplied.

Source

Thrown at comfy/ldm/seedvr/model.py:1265

        neg_cond, pos_cond = context.chunk(2, dim=0)
        if pos_cond.shape[0] == 1:
            pos_cond, neg_cond = pos_cond.squeeze(0), neg_cond.squeeze(0)
            return flatten([pos_cond, neg_cond])
        return flatten((*pos_cond.unbind(0), *neg_cond.unbind(0)))

    @staticmethod
    def _seedvr2_is_single_conditioning_branch(cond_or_uncond):
        if cond_or_uncond is None or len(cond_or_uncond) == 0:
            return False
        first = cond_or_uncond[0]
        return all(entry == first for entry in cond_or_uncond)

    @staticmethod
    def _check_seedvr2_video_latent(x, channels, name):
        if x.ndim != 5:
            raise ValueError(f"SeedVR2 expected {name} to be 5-D native latent, got shape {tuple(x.shape)}.")
        if x.shape[1] != channels:
            raise ValueError(f"SeedVR2 expected {name} channels to be {channels}, got shape {tuple(x.shape)}.")
        return x

    def _swap_pos_neg_halves(self, out, cond_or_uncond=None):
        if NaDiT._seedvr2_is_single_conditioning_branch(cond_or_uncond):
            return out
        pos, neg = out.chunk(2, dim=0)
        return torch.cat([neg, pos], dim=0)

    def forward(
        self,
        x,
        timestep,
        context,  # l c
        disable_cache: bool = False,
        **kwargs
    ):
        transformer_options = kwargs.get("transformer_options", {})
        patches_replace = transformer_options.get("patches_replace", {})

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Generate the conditioning latent with the SeedVR2Conditioning node so channel counts are exact.
  2. If building by hand, append exactly one mask channel to the LQ latent: cond = torch.cat([lq_latent, mask], dim=1).
  3. Encode inputs only with the SeedVR2 VAE; remove incompatible VAE overrides.
  4. Compare x.shape[1] with the expected value printed in the message to identify which tensor is wrong.

Example fix

# before
cond = lq_latent  # same channels as x
# after
mask = torch.ones_like(lq_latent[:, :1])
cond = torch.cat([lq_latent, mask], dim=1)  # latent_channels + 1
Defensive patterns

Strategy: validation

Validate before calling

def check_latent_channels(x, expected, name):
    if x.shape[1] != expected:
        raise ValueError(f"{name} must have {expected} channels, got {x.shape[1]} (shape {tuple(x.shape)})")
    return x

Type guard

def channels_match(x, expected) -> bool:
    return x.dim() == 5 and x.shape[1] == expected

Prevention

When it happens

Trigger: Passing a conditioning latent with the same channel count as the noise latent (missing the extra conditioning channel); using a non-SeedVR2 VAE to encode; concatenating a mask incorrectly so channel count is off by more or less than one.

Common situations: Building SeedVR2 conditioning by hand instead of using SeedVR2Conditioning; swapping in an SD VAE (4-ch) or other VAE encode output; a conversion script that drops the appended mask channel.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/e7a4849e61e96f5c. Report an issue: GitHub.