tracel-ai/burn · error
Channels must be divisible by the number of groups. Got chan
Error message
Channels must be divisible by the number of groups. Got channels_in={}, offset_groups={} What it means
DeformConv2d requires the input channel count to be divisible by `offset_groups`, because offsets are predicted per group of input channels. In `DeformConv2dConfig::init`, after the generic grouped-conv check, a separate check panics when `channels[0] % offset_groups != 0`.
Source
Thrown at crates/burn-nn/src/modules/conv/deform_conv2d.rs:85
pub dilation: [usize; 2],
/// Controls the connections between input and output channels.
pub weight_groups: usize,
/// Offset groups.
pub offset_groups: usize,
/// The padding configuration.
#[module(skip)]
pub padding: PaddingConfig2d,
}
impl DeformConv2dConfig {
/// Initialize a new [DeformConv2d](DeformConv2d) module.
pub fn init(&self, device: &Device) -> DeformConv2d {
checks::checks_channels_div_groups(self.channels[0], self.channels[1], self.weight_groups);
if self.padding == PaddingConfig2d::Same {
checks::check_same_padding_support(&self.kernel_size);
}
if !self.channels[0].is_multiple_of(self.offset_groups) {
panic!(
"Channels must be divisible by the number of groups. Got \
channels_in={}, offset_groups={}",
self.channels[0], self.offset_groups
);
}
let shape = [
self.channels[1],
self.channels[0] / self.weight_groups,
self.kernel_size[0],
self.kernel_size[1],
];
let k = self.kernel_size.iter().product::<usize>();
let fan_in = self.channels[0] / self.weight_groups * k;
let fan_out = self.channels[1] / self.weight_groups * k;
let weight = selfView on GitHub (pinned to d16f7ba2ed)
Solutions
- Set `offset_groups` to a divisor of channels_in (common values: 1, 4, 8 with channels_in a multiple of them).
- Change the input channel count (e.g. via an initial conv) so it is divisible by offset_groups.
- Set offset_groups = 1 to use a single offset group.
- Also ensure channels_in/channels_out are divisible by `weight_groups` (separate check that runs first).
Example fix
// before
let config = DeformConv2dConfig { channels: [3, 64], offset_groups: 8, ..Default::default() }; // 3 % 8 != 0
// after
let config = DeformConv2dConfig { channels: [3, 64], offset_groups: 1, ..Default::default() }; Defensive patterns
Strategy: validation
Validate before calling
fn validate_deform_conv(config: &DeformConv2dConfig) {
assert!(config.channels[0].is_multiple_of(config.offset_groups),
"channels_in={} not divisible by offset_groups={}", config.channels[0], config.offset_groups);
assert!(config.channels[0].is_multiple_of(config.weight_groups));
assert!(config.channels[1].is_multiple_of(config.weight_groups));
}
validate_deform_conv(&config); Type guard
fn deform_groups_valid(channels_in: usize, channels_out: usize, offset_groups: usize, weight_groups: usize) -> bool {
channels_in.is_multiple_of(offset_groups)
&& channels_in.is_multiple_of(weight_groups)
&& channels_out.is_multiple_of(weight_groups)
} Try / catch
let result = std::panic::catch_unwind(|| config.init(&device));
match result {
Ok(layer) => layer,
Err(_) => {
let mut c = config;
c.offset_groups = 1;
c.init(&device)
}
} Prevention
- Keep offset_groups at 1 unless channels_in is known to be a multiple (e.g. 8 | 256).
- Assert divisibility when loading configs from checkpoints/JSON.
- Remember two independent checks: offset_groups vs channels_in, and weight_groups vs both channels.
When it happens
Trigger: Building a `DeformConv2d` via `DeformConv2dConfig::init(&device)` where `channels[0]` (in channels) is not a multiple of `offset_groups`, e.g. channels=[3, 64] with offset_groups=8.
Common situations: Copying a config that used offset_groups=8 with 256-channel inputs onto an RGB 3-channel input; tuning offset_groups without updating channels; default configs mismatched with a new first layer.
Related errors
- Both channels must be divisible by the number of groups. Got
- expand: cannot expand dimension {} from {} to {}
- Dropout probability should be between 0 and 1, but got {}
- Scale factor is too large
- Either output_size or scale_factor must be provided
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/972f6c0ee9ea8896.
Report an issue: GitHub.