huggingface/candle · error · candle::Error
unexpected num-channels in GroupNorm ({n_channels} <> {}
Error message
unexpected num-channels in GroupNorm ({n_channels} <> {} What it means
During forward, GroupNorm checks that the input's channel dimension (dims[1]) matches the num_channels the layer was constructed with. This bail fires when they differ. Note the message itself has a malformed format string (a stray '{}') but the data reported is the actual channel count vs the configured one.
Source
Thrown at candle-nn/src/group_norm.rs:48
weight,
bias,
eps,
num_channels,
num_groups,
})
}
}
impl crate::Module for GroupNorm {
fn forward(&self, x: &Tensor) -> Result<Tensor> {
let x_shape = x.dims();
if x_shape.len() <= 2 {
candle::bail!("input rank for GroupNorm should be at least 3");
}
let (b_sz, n_channels) = (x_shape[0], x_shape[1]);
let hidden_size = x_shape[2..].iter().product::<usize>() * n_channels / self.num_groups;
if n_channels != self.num_channels {
candle::bail!(
"unexpected num-channels in GroupNorm ({n_channels} <> {}",
self.num_channels
)
}
let x_dtype = x.dtype();
let internal_dtype = match x_dtype {
DType::F16 | DType::BF16 => DType::F32,
d => d,
};
let x = x.reshape((b_sz, self.num_groups, hidden_size))?;
let x = x.to_dtype(internal_dtype)?;
let mean_x = (x.sum_keepdim(2)? / hidden_size as f64)?;
let x = x.broadcast_sub(&mean_x)?;
let norm_x = (x.sqr()?.sum_keepdim(2)? / hidden_size as f64)?;
let x_normed = x.broadcast_div(&(norm_x + self.eps)?.sqrt()?)?;
let mut w_dims = vec![1; x_shape.len()];
w_dims[1] = n_channels;
let weight = self.weight.reshape(w_dims.clone())?;View on GitHub (pinned to d5fee525bf)
Solutions
- Construct GroupNorm with num_channels equal to the input's dim 1 — derive it from the preceding layer's out_channels.
- If loading weights, verify the GroupNorm weight shape (weight.dims()[0]) matches the model's channel count for that layer.
- Check the tensor order: a transposed tensor (channels last) will present the wrong dim at index 1; permute before forward.
- Fix the layer wiring if a GroupNorm instance is shared between two branches with different channel widths; create one per width.
Example fix
// before let norm = GroupNorm::new(w, b, 64, 32, 1e-5)?; let y = norm.forward(&conv_out)?; // conv_out dims [B, 128, H, W] // after let c = conv_out.dims()[1]; let norm = GroupNorm::new(w, b, c, 32, 1e-5)?; let y = norm.forward(&conv_out)?;
Defensive patterns
Strategy: validation
Validate before calling
let c_in = x.dims()[1];
if c_in != norm.num_channels() {
return Err(anyhow!("input has {c_in} channels, GroupNorm built for {}", norm.num_channels()));
} Type guard
fn channels_match(norm: &candle_nn::GroupNorm, x: &Tensor) -> bool {
x.rank() >= 2 && x.dims()[1] == norm.num_channels()
} Try / catch
let y = match norm.forward(&x) {
Ok(y) => y,
Err(e) if e.to_string().contains("num-channels") => {
let c = x.dims()[1];
let (w, b) = rebuild_norm_weights(c)?; // or permute x if channels-last
GroupNorm::new(w, b, c, 32, 1e-5)?.forward(&x)?
}
Err(e) => return Err(e.into()),
}; Prevention
- Build GroupNorm layers in code from the previous layer's channel count, not duplicated constants
- When loading checkpoints, verify each GroupNorm weight shape matches the rebuilt layer
- If tensors are channels-last, permute to channels-first before norm layers
- Never share one GroupNorm instance between branches of different widths
When it happens
Trigger: Calling forward on a GroupNorm built for N channels with an input tensor whose second dimension is a different channel count — e.g. GroupNorm configured for 64 channels receiving a tensor with 128 channels.
Common situations: Reusing a norm layer across architecture stages with different widths; loading a checkpoint whose channel count differs from the freshly built model; model config edited (width multiplier) without updating the norm layers; wrong tensor passed to forward.
Related errors
- input rank for GroupNorm should be at least 3
- the target tensor should have a single dimension ({dims:?})
- the target tensor should have two dimensions ({dims:?})
- cross_entropy expects an input tensor of rank 2
- backward not supported for non uniform upscaling factors
AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02).
Data as JSON: /api/errors/20e3c2ce96473b08.
Report an issue: GitHub.