huggingface/candle · error · candle::Error

input rank for GroupNorm should be at least 3

Error message

input rank for GroupNorm should be at least 3

What it means

GroupNorm::forward requires input of rank >= 3: dimension 0 is batch, dimension 1 is channels, and the remaining dims form the spatial/feature extent. This bail fires when the tensor passed to forward has 2 or fewer dimensions, since GroupNorm cannot identify a channel axis in such input.

Source

Thrown at candle-nn/src/group_norm.rs:43

            candle::bail!(
                "GroupNorm: num_groups ({num_groups}) must divide num_channels ({num_channels})"
            )
        }
        Ok(Self {
            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)?;

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Reshape the input to at least 3 dims, e.g. x.reshape((b, c, ()))? or restore spatial dims before forward.
  2. If the input is genuinely [B, C] features, use LayerNorm (candle_nn::layer_norm) instead of GroupNorm.
  3. Audit the module pipeline: GroupNorm should sit after conv-like layers producing [B, C, ...]; move it or replace it if placed after a flatten.
  4. Add a debug assert on x.rank() >= 3 in your forward path to catch this early.

Example fix

// before
let x = x.flatten_all()?; // rank 1
let x = group_norm.forward(&x)?; // error
// after
let x = x.reshape((b, c, hw))?;
let x = group_norm.forward(&x)?;
Defensive patterns

Strategy: type-guard

Validate before calling

if x.rank() < 3 {
    return Err(anyhow!("GroupNorm needs rank>=3 input, got {}", x.rank()));
}

Type guard

fn is_group_norm_input(x: &Tensor) -> bool { x.rank() >= 3 }

fn forward_gn(gn: &candle_nn::GroupNorm, x: &Tensor) -> candle::Result<Tensor> {
    if !is_group_norm_input(x) {
        candle::bail!("expected rank>=3 tensor for GroupNorm, got rank {}", x.rank());
    }
    gn.forward(x)
}

Try / catch

let x = match group_norm.forward(&x) {
    Ok(y) => y,
    Err(e) if e.to_string().contains("rank") => {
        let b = x.dim(0)?; let c = x.dim(1)?;
        group_norm.forward(&x.reshape((b, c, ()))?)?
    }
    Err(e) => return Err(e.into()),
};

Prevention

When it happens

Trigger: Calling forward on the GroupNorm module (directly or through Module::forward) with a tensor of shape [B, C] or [C] — e.g. feeding a flattened feature vector or a 2D logits tensor into GroupNorm.

Common situations: Applying GroupNorm to MLP/transformer activations of shape [B, C] where LayerNorm was intended; forgetting to reshape flattened conv output back to [B, C, H*W]; wrong tensor routed through a Sequential that ends with GroupNorm.

Related errors


AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02). Data as JSON: /api/errors/01fa80001b61f8f0. Report an issue: GitHub.