{"record":{"id":"2074ec3d1669de2a","repo":"huggingface/candle","slug":"groupnorm-num-groups-num-groups-must-divide-n","errorCode":null,"errorMessage":"GroupNorm: num_groups ({num_groups}) must divide num_channels ({num_channels})","messagePattern":"GroupNorm: num_groups \\((.+?)\\) must divide num_channels \\((.+?)\\)","errorType":"exception","errorClass":"candle::Error","httpStatus":null,"severity":"error","filePath":"candle-nn/src/group_norm.rs","lineNumber":25,"sourceCode":"#[derive(Clone, Debug)]\npub struct GroupNorm {\n    weight: Tensor,\n    bias: Tensor,\n    eps: f64,\n    num_channels: usize,\n    num_groups: usize,\n}\n\nimpl GroupNorm {\n    pub fn new(\n        weight: Tensor,\n        bias: Tensor,\n        num_channels: usize,\n        num_groups: usize,\n        eps: f64,\n    ) -> Result<Self> {\n        if !num_channels.is_multiple_of(num_groups) {\n            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\");","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-nn/src/group_norm.rs#L7-L43","documentation":"GroupNorm::new validates the layer configuration: the channel count must be evenly divisible by the number of groups, because GroupNorm splits channels into groups before normalizing. This bail fires at construction time when num_channels is not a multiple of num_groups.","triggerScenarios":"Calling candle_nn::GroupNorm::new(weight, bias, num_channels, num_groups, eps) where num_channels % num_groups != 0 (e.g. 48 channels with 5 groups).","commonSituations":"Copying a config from a paper whose architecture used a different channel count; typo in group count; adapting a pretrained checkpoint whose conv layers have channel counts incompatible with your chosen groups; generic configs where channels come from a previous layer that changed.","solutions":["Pick a num_groups that divides num_channels (e.g. for 48 channels use 2, 3, 4, 6, 8, 12, 16, 24 or 48).","Common convention: num_groups = 32 (as in BigGAN/ADaPT-style nets) only works when channels % 32 == 0; otherwise fall back to fewer groups or LayerNorm (groups == 1).","Compute groups programmatically: let num_groups = gcd(num_channels, desired_groups) or clamp to largest divisor <= 32.","If channels come from a checkpoint, print/inspect the weight shape and derive num_channels from weight.dims()[0]."],"exampleFix":"// before\nlet norm = GroupNorm::new(w, b, 48, 32, 1e-5)?; // 48 % 32 != 0\n// after\nlet num_groups = 48.min(32); let num_groups = (1..=num_groups).rev().find(|g| 48 % g == 0).unwrap();\nlet norm = GroupNorm::new(w, b, 48, num_groups, 1e-5)?;","handlingStrategy":"validation","validationCode":"fn check_group_norm(channels: usize, groups: usize) -> Result<(), String> {\n    if channels.is_multiple_of(groups) { Ok(()) } else {\n        Err(format!(\"channels {channels} not divisible by groups {groups}\"))\n    }\n}","typeGuard":"fn valid_group_norm_config(num_channels: usize, num_groups: usize) -> bool {\n    num_channels.is_multiple_of(num_groups) && num_groups >= 1\n}","tryCatchPattern":"match GroupNorm::new(w.clone(), b.clone(), channels, groups, 1e-5) {\n    Ok(gn) => gn,\n    Err(e) => {\n        let groups = (1..=32).rev().find(|g| channels % g == 0).unwrap_or(1);\n        GroupNorm::new(w, b, channels, groups, 1e-5)?\n    }\n}","preventionTips":["Derive num_channels from the preceding conv layer's out_channels, never hard-code","Pick groups from the divisor list of channels (32 is only valid when channels % 32 == 0)","Add a builder helper that auto-selects the largest group count <= 32 dividing the channels","When porting architectures, compare channel/group config against the reference implementation"],"tags":["config","normalization","validation","rust"],"backgroundTag":"invalid-configuration","analyzedSha":"d5fee525bfde3273eb7c9b75fd2bc4937be867ca","analyzedAt":"2026-09-02T00:15:47.023Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}