Comfy-Org/ComfyUI · error · ValueError

SeedVR2 downsample expected {self.channels} channels, got {h

Error message

SeedVR2 downsample expected {self.channels} channels, got {hidden_states.shape[1]}.

What it means

SeedVR2VaeDownsample validates that the input channel count equals self.channels before its strided conv, which is weight-shaped for exactly that count. A mismatch means the block graph or config is inconsistent (previous block's out_channels != this block's channels). Like the upsample check, this is a construction/config error surfaced early with exact numbers.

Source

Thrown at comfy/ldm/seedvr/vae.py:773

        self.conv = InflatedCausalConv3d(
            self.channels,
            self.out_channels,
            kernel_size=(self.temporal_kernel, self.spatial_kernel, self.spatial_kernel),
            stride=(self.temporal_ratio, self.spatial_ratio, self.spatial_ratio),
            padding=(1 if self.temporal_down else 0, 0, 0),
            inflation_mode=inflation_mode,
        )


    def forward(
        self,
        hidden_states: torch.FloatTensor,
        memory_state = None,
        memory_cache = None,
    ) -> torch.FloatTensor:

        if hidden_states.shape[1] != self.channels:
            raise ValueError(f"SeedVR2 downsample expected {self.channels} channels, got {hidden_states.shape[1]}.")

        if self.spatial_down:
            pad = (0, 1, 0, 1)
            hidden_states = F.pad(hidden_states, pad, mode="constant", value=0)

        if hidden_states.shape[1] != self.channels:
            raise ValueError(f"SeedVR2 downsample expected {self.channels} channels after padding, got {hidden_states.shape[1]}.")

        hidden_states = self.conv(hidden_states, memory_state=memory_state, memory_cache=memory_cache)

        return hidden_states


class ResnetBlock3D(nn.Module):
    def __init__(
        self,
        in_channels: int,
        out_channels: Optional[int] = None,

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Align the downsample's channels with the previous block's output channels in the config.
  2. Validate the whole block_out_channels progression in the encoder/decoder config matches the official SeedVR2 VAE.
  3. When loading fails oddly after config edits, re-derive channels from the checkpoint's conv weight shapes.
  4. Prefer using SeedVR2Encoder/SeedVR2Decoder constructors, which compute channels consistently.
Defensive patterns

Strategy: validation

Validate before calling

def validate_downsample_input(block, hidden_states):
    if hidden_states.shape[1] != block.channels:
        raise ValueError(f"block expects {block.channels} channels, got {hidden_states.shape[1]}; fix VAE config")
    return hidden_states

Type guard

def channels_match_block(x, block) -> bool:
    return x.dim() >= 2 and x.shape[1] == block.channels

Prevention

When it happens

Trigger: Building an encoder where DownEncoderBlock3D output channels do not match the following downsample's channels; editing block_out_channels lists of different lengths; mismatched checkpoint weights loaded into a config with different channel widths.

Common situations: Custom VAE configurations with inconsistent channel progressions; state-dict/config mismatches after checkpoint conversion; experimental architecture edits.

Related errors


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