Comfy-Org/ComfyUI · error · ValueError
Input latent has {lq_latent.shape[1]} channels, this model v
Error message
Input latent has {lq_latent.shape[1]} channels, this model variant expects {expected_c}. Flux1/SD3 = 16 channels, Flux2 = 128 channels. What it means
PidNet checks that the supplied lq_latent channel count matches the channel count its lq projection was configured for (latent_channels of the loaded variant). Flux1/SD3 VAE latents have 16 channels while Flux2 uses 128, so mixing a Flux2 PiD model with a Flux1/SD3 VAE latent (or vice versa) fails here. The error text includes both observed and expected counts, making diagnosis direct.
Source
Thrown at comfy/ldm/pixeldit/pid.py:239
def _pre_patch_block(self, s, i, pid_lq_features, pid_degrade_sigma, **kwargs):
if not self.lq_proj.is_gate_active(i):
return s
out_idx = self.lq_proj.output_index(i)
if out_idx >= len(pid_lq_features):
return s
return self.lq_proj.gate(s, pid_lq_features[out_idx], pid_degrade_sigma, out_idx)
def _pre_pixel_blocks(self, s, pid_pit_lq_feature=None, pid_degrade_sigma=None, **kwargs):
if pid_pit_lq_feature is None:
return s
return self.pit_lq_gate(s, pid_pit_lq_feature, pid_degrade_sigma)
def _forward(self, x, timesteps, context=None, attention_mask=None, transformer_options={}, lq_latent=None, degrade_sigma=None, **kwargs):
if lq_latent is None:
raise ValueError("PidNet requires lq_latent — attach via PiDConditioning")
expected_c = self.lq_proj.latent_channels
if lq_latent.shape[1] != expected_c:
raise ValueError(
f"Input latent has {lq_latent.shape[1]} channels, this model variant expects {expected_c}. "
f"Flux1/SD3 = 16 channels, Flux2 = 128 channels."
)
B = x.shape[0]
# Match the backbone's pad_to_patch_size (round up) so the LQ grid lines up with the patch stream.
Hs = -(-x.shape[2] // self.patch_size)
Ws = -(-x.shape[3] // self.patch_size)
degrade_sigma = degrade_sigma.to(device=x.device, dtype=torch.float32).reshape(-1)
if degrade_sigma.numel() == 1 and B > 1:
degrade_sigma = degrade_sigma.expand(B).contiguous()
lq_features = self.lq_proj(lq_latent=lq_latent.to(x), target_pH=Hs, target_pW=Ws)
pit_lq_feature = lq_features.pop() if self.pit_lq_inject else None
return super()._forward(
x, timesteps,
context=context, attention_mask=attention_mask,View on GitHub (pinned to 1c6d8d45b3)
Solutions
- Match families: use the PiD variant trained for your base model (16-channel variant for Flux1/SD3, 128-channel variant for Flux2).
- Encode the LQ image with the same VAE as the target model — do not mix a Flux1 VAE encode into a Flux2 workflow.
- Check for a VAE override node forcing an incompatible VAE and remove it.
- Read the printed expected_c in the message and compare with your latent's channel dimension to confirm which side is wrong.
Defensive patterns
Strategy: validation
Validate before calling
def check_pid_channels(lq_latent, expected_channels):
c = lq_latent.shape[1]
if c != expected_channels:
raise ValueError(
f"LQ latent has {c} channels but this PiD variant expects {expected_channels}; "
"match the PiD variant to your base model family (Flux1/SD3=16, Flux2=128)"
)
return lq_latent Type guard
def matches_pid_variant(lq_latent, variant) -> bool:
expected = {"flux1": 16, "sd3": 16, "flux2": 128}[variant]
return lq_latent.shape[1] == expected Prevention
- Keep PiD adapters and base models from the same family in one workflow.
- Encode LQ images with the same VAE as the target model.
- Log expected vs actual channel counts when building custom conditioning code.
When it happens
Trigger: Attaching a PiD model variant built for 128-channel Flux2 latents but feeding a 16-channel SD3/Flux1 latent through PiDConditioning; or the reverse pairing. Also triggered by using a custom VAE with a non-standard latent channel count.
Common situations: Mixing checkpoints from different model families in one workflow (Flux2 base model with Flux1 PiD adapter); swapping the VAE override to an incompatible VAE; manually encoding the LQ image with the wrong VAE encode node.
Related errors
- PidNet requires lq_latent — attach via PiDConditioning
- Input img and txt tensors must have 3 dimensions.
- Hidden size {params.hidden_size} must be divisible by num_he
- Got {params.axes_dim} but expected positional dim {pe_dim}
- Input img and txt tensors must have 3 dimensions.
AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14).
Data as JSON: /api/errors/6a21d8f9b17f1c97.
Report an issue: GitHub.