tracel-ai/burn · error

input rank for GroupNorm should be at least 3, but got {}

Error message

input rank for GroupNorm should be at least 3, but got {}

What it means

GroupNorm in burn-nn panics when the input tensor's rank (number of dimensions) is less than 3. GroupNorm normalizes over the channel dimension within each batch sample, so it requires at least [batch, channels, spatial...] shaped input. Rather than returning a Result, group_norm panics immediately because a rank < 3 input is always a programming error.

Source

Thrown at crates/burn-nn/src/modules/norm/group.rs:160

/// - `Y` is the output tensor
/// - `γ` is the learnable weight
/// - `β` is the learnable bias
///
pub(crate) fn group_norm<const D: usize>(
    input: Tensor<D>,
    gamma: Option<Tensor<1>>,
    beta: Option<Tensor<1>>,
    num_groups: usize,
    epsilon: f64,
    affine: bool,
) -> Tensor<D> {
    if (beta.is_none() || gamma.is_none()) && affine {
        panic!("Affine is set to true, but gamma or beta is None");
    }

    let shape = input.shape();
    if shape.num_elements() <= 2 {
        panic!(
            "input rank for GroupNorm should be at least 3, but got {}",
            shape.num_elements()
        );
    }

    let batch_size = shape[0];
    let num_channels = shape[1];

    let hidden_size = shape[2..].iter().product::<usize>() * num_channels / num_groups;
    let input = input.reshape([batch_size, num_groups, hidden_size]);

    // Widen before the reduction when the input dtype cannot hold a sum of
    // squares (see [`accumulation_dtype`]); `square()` below is what overflows.
    // Narrowed again straight after, so the affine still runs at the model's
    // own dtype and only the statistics pay for the wider arithmetic.
    let original: FloatDType = input.dtype().into();
    let widened = accumulation_dtype(input.dtype());
    let input = match widened {

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Reshape the input to at least 3 dimensions ([batch, channels, ...]) before calling forward on GroupNorm.
  2. Check input.dims().len() >= 3 (and > 2 elements) before invoking group_norm.
  3. Audit the layer order so normalization happens before any flatten/reshape to 2D.

Example fix

// before
let logits = model(x);            // shape [batch, classes]
let out = group_norm.forward(logits); // panics: rank 2
// after
let features = features.reshape([batch, channels, spatial]);
let normed = group_norm.forward(features);
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_groupnorm_rank<B: burn::tensor::backend::Backend>(x: &burn::tensor::Tensor<B, 2>) -> burn::tensor::Tensor<B, 3> {
    // rank < 3 would panic inside group_norm; reshape to [1, C, N] minimum
    x.reshape([1, x.dims()[0], x.dims()[1]])
}

Type guard

fn is_valid_groupnorm_input(shape: &[usize]) -> bool {
    shape.len() >= 3
}

Try / catch

// panic-based API: validate before calling instead of catching
if !is_valid_groupnorm_input(&input.dims()) {
    input = input.reshape([...]); // fix rank before forward
}
let out = group_norm.forward(input);

Prevention

When it happens

Trigger: Calling group_norm (via GroupNorm::forward or forward_with_slicing) with a tensor of rank 2 or lower, e.g. a flattened tensor of shape [N, C] or a single [C] vector.

Common situations: Feeding a flattened tensor straight from a Linear layer into GroupNorm; forgetting to reshape after a squeeze/view; passing a 1D bias-like tensor; misconfigured model that removes the spatial dims before normalization.

Related errors


AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05). Data as JSON: /api/errors/a1930cfd4f95cc90. Report an issue: GitHub.