{"record":{"id":"b89a2aab5de45133","repo":"invoke-ai/InvokeAI","slug":"in-channels-must-be-divisible-by-groups","errorCode":null,"errorMessage":"in_channels must be divisible by groups","messagePattern":"in_channels must be divisible by groups","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/image_util/pidi/model.py","lineNumber":353,"sourceCode":"            else:\n                buffer = torch.zeros(shape[0], shape[1], 5 * 5).to(weights.device)\n            weights = weights.view(shape[0], shape[1], -1)\n            buffer[:, :, [0, 2, 4, 10, 14, 20, 22, 24]] = weights[:, :, 1:]\n            buffer[:, :, [6, 7, 8, 11, 13, 16, 17, 18]] = -weights[:, :, 1:]\n            buffer[:, :, 12] = 0\n            buffer = buffer.view(shape[0], shape[1], 5, 5)\n            y = F.conv2d(x, buffer, bias, stride=stride, padding=padding, dilation=dilation, groups=groups)\n            return y\n        return func\n    else:\n        print('impossible to be here unless you force that')\n        return None\n\nclass Conv2d(nn.Module):\n    def __init__(self, pdc, in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=False):\n        super(Conv2d, self).__init__()\n        if in_channels % groups != 0:\n            raise ValueError('in_channels must be divisible by groups')\n        if out_channels % groups != 0:\n            raise ValueError('out_channels must be divisible by groups')\n        self.in_channels = in_channels\n        self.out_channels = out_channels\n        self.kernel_size = kernel_size\n        self.stride = stride\n        self.padding = padding\n        self.dilation = dilation\n        self.groups = groups\n        self.weight = nn.Parameter(torch.Tensor(out_channels, in_channels // groups, kernel_size, kernel_size))\n        if bias:\n            self.bias = nn.Parameter(torch.Tensor(out_channels))\n        else:\n            self.register_parameter('bias', None)\n        self.reset_parameters()\n        self.pdc = pdc\n\n    def reset_parameters(self):","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/image_util/pidi/model.py#L335-L371","documentation":"The PidiNet model's Conv2d wrapper validates group-convolution arguments like nn.Conv2d does: in_channels must be an integer multiple of groups. It raises ValueError('in_channels must be divisible by groups') in __init__ when that invariant is violated, before any weight tensors are created.","triggerScenarios":"Constructing invokeai/backend/image_util/pidi/model.py Conv2d(pdc, in_channels, out_channels, kernel_size, ..., groups=g) where in_channels % g != 0 — e.g. in_channels=3 with groups=2, or any groups > 1 that does not evenly divide the input channel count.","commonSituations":"Hand-editing the network to add depthwise (groups=in_channels) or grouped convolutions and miscounting channels; changing the input channel count (e.g. grayscale or 4-channel input) without updating grouped layers; porting layers from another model with different channel widths.","solutions":["Set groups=1 (the default) unless grouped convolutions are specifically required.","For depthwise convolutions use groups=in_channels (which trivially divides itself).","Adjust in_channels (or the preceding layer's out_channels) so it is an integer multiple of groups.","Reduce groups to a divisor of in_channels, e.g. groups = gcd(in_channels, desired_groups)."],"exampleFix":"// before\nconv = Conv2d(pdc, in_channels=3, out_channels=32, kernel_size=3, groups=2)  # 3 % 2 != 0\n// after\nconv = Conv2d(pdc, in_channels=4, out_channels=32, kernel_size=3, groups=2)  # or groups=1","handlingStrategy":"validation","validationCode":"if groups > 1 and in_channels % groups != 0:\n    raise ValueError(f'in_channels={in_channels} not divisible by groups={groups}')","typeGuard":null,"tryCatchPattern":"try:\n    conv = Conv2d(pdc, in_channels, out_channels, kernel_size, groups=groups)\nexcept ValueError as e:\n    if 'divisible by groups' in str(e):\n        groups = 1\n        conv = Conv2d(pdc, in_channels, out_channels, kernel_size, groups=groups)\n    else:\n        raise","preventionTips":["Default to groups=1; only opt into grouped convolutions deliberately.","For depthwise layers, set groups=in_channels so the divisibility invariant holds by construction.","When changing channel counts, recompute every dependent layer's groups in one place.","Sanity-check configurations with a small forward pass at build time."],"tags":["python","pytorch","convolution","invalid-argument"],"backgroundTag":"in-channels-divisible-by-groups","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}