{"record":{"id":"01fa80001b61f8f0","repo":"huggingface/candle","slug":"input-rank-for-groupnorm-should-be-at-least-3","errorCode":null,"errorMessage":"input rank for GroupNorm should be at least 3","messagePattern":"input rank for GroupNorm should be at least 3","errorType":"exception","errorClass":"candle::Error","httpStatus":null,"severity":"error","filePath":"candle-nn/src/group_norm.rs","lineNumber":43,"sourceCode":"            candle::bail!(\n                \"GroupNorm: num_groups ({num_groups}) must divide num_channels ({num_channels})\"\n            )\n        }\n        Ok(Self {\n            weight,\n            bias,\n            eps,\n            num_channels,\n            num_groups,\n        })\n    }\n}\n\nimpl crate::Module for GroupNorm {\n    fn forward(&self, x: &Tensor) -> Result<Tensor> {\n        let x_shape = x.dims();\n        if x_shape.len() <= 2 {\n            candle::bail!(\"input rank for GroupNorm should be at least 3\");\n        }\n        let (b_sz, n_channels) = (x_shape[0], x_shape[1]);\n        let hidden_size = x_shape[2..].iter().product::<usize>() * n_channels / self.num_groups;\n        if n_channels != self.num_channels {\n            candle::bail!(\n                \"unexpected num-channels in GroupNorm ({n_channels} <> {}\",\n                self.num_channels\n            )\n        }\n        let x_dtype = x.dtype();\n        let internal_dtype = match x_dtype {\n            DType::F16 | DType::BF16 => DType::F32,\n            d => d,\n        };\n        let x = x.reshape((b_sz, self.num_groups, hidden_size))?;\n        let x = x.to_dtype(internal_dtype)?;\n        let mean_x = (x.sum_keepdim(2)? / hidden_size as f64)?;\n        let x = x.broadcast_sub(&mean_x)?;","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-nn/src/group_norm.rs#L25-L61","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Reshape the input to at least 3 dims, e.g. x.reshape((b, c, ()))? or restore spatial dims before forward.","If the input is genuinely [B, C] features, use LayerNorm (candle_nn::layer_norm) instead of GroupNorm.","Audit the module pipeline: GroupNorm should sit after conv-like layers producing [B, C, ...]; move it or replace it if placed after a flatten.","Add a debug assert on x.rank() >= 3 in your forward path to catch this early."],"exampleFix":"// before\nlet x = x.flatten_all()?; // rank 1\nlet x = group_norm.forward(&x)?; // error\n// after\nlet x = x.reshape((b, c, hw))?;\nlet x = group_norm.forward(&x)?;","handlingStrategy":"type-guard","validationCode":"if x.rank() < 3 {\n    return Err(anyhow!(\"GroupNorm needs rank>=3 input, got {}\", x.rank()));\n}","typeGuard":"fn is_group_norm_input(x: &Tensor) -> bool { x.rank() >= 3 }\n\nfn forward_gn(gn: &candle_nn::GroupNorm, x: &Tensor) -> candle::Result<Tensor> {\n    if !is_group_norm_input(x) {\n        candle::bail!(\"expected rank>=3 tensor for GroupNorm, got rank {}\", x.rank());\n    }\n    gn.forward(x)\n}","tryCatchPattern":"let x = match group_norm.forward(&x) {\n    Ok(y) => y,\n    Err(e) if e.to_string().contains(\"rank\") => {\n        let b = x.dim(0)?; let c = x.dim(1)?;\n        group_norm.forward(&x.reshape((b, c, ()))?)?\n    }\n    Err(e) => return Err(e.into()),\n};","preventionTips":["Keep GroupNorm only after conv/spatial layers producing [B, C, ...]; use LayerNorm for [B, C] features","Avoid flatten_all before normalization layers; reshape back to 3-D first","Assert tensor rank in a small wrapper around your norm modules","Document expected shapes on your custom Module impls"],"tags":["tensor","shape","normalization","rust"],"backgroundTag":"tensor-rank-mismatch","analyzedSha":"d5fee525bfde3273eb7c9b75fd2bc4937be867ca","analyzedAt":"2026-09-02T00:15:47.023Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}