{"record":{"id":"7d434adbebac170d","repo":"open-mmlab/mmdetection","slug":"num-branches-num-branches-num-channels-len","errorCode":null,"errorMessage":"NUM_BRANCHES({num_branches}) != NUM_CHANNELS({len(num_channels)})","messagePattern":"NUM_BRANCHES\\((.+?)\\) != NUM_CHANNELS\\((.+?)\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mmdet/models/backbones/hrnet.py","lineNumber":59,"sourceCode":"        self.norm_cfg = norm_cfg\n        self.conv_cfg = conv_cfg\n        self.with_cp = with_cp\n        self.branches = self._make_branches(num_branches, blocks, num_blocks,\n                                            num_channels)\n        self.fuse_layers = self._make_fuse_layers()\n        self.relu = nn.ReLU(inplace=False)\n\n    def _check_branches(self, num_branches, num_blocks, in_channels,\n                        num_channels):\n        if num_branches != len(num_blocks):\n            error_msg = f'NUM_BRANCHES({num_branches}) ' \\\n                        f'!= NUM_BLOCKS({len(num_blocks)})'\n            raise ValueError(error_msg)\n\n        if num_branches != len(num_channels):\n            error_msg = f'NUM_BRANCHES({num_branches}) ' \\\n                        f'!= NUM_CHANNELS({len(num_channels)})'\n            raise ValueError(error_msg)\n\n        if num_branches != len(in_channels):\n            error_msg = f'NUM_BRANCHES({num_branches}) ' \\\n                        f'!= NUM_INCHANNELS({len(in_channels)})'\n            raise ValueError(error_msg)\n\n    def _make_one_branch(self,\n                         branch_index,\n                         block,\n                         num_blocks,\n                         num_channels,\n                         stride=1):\n        downsample = None\n        if stride != 1 or \\\n                self.in_channels[branch_index] != \\\n                num_channels[branch_index] * block.expansion:\n            downsample = nn.Sequential(\n                build_conv_layer(","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/open-mmlab/mmdetection/blob/cfd5d3a985b0249de009b67d04f37263e11cdf3d/mmdet/models/backbones/hrnet.py#L41-L77","documentation":"HRNet's _check_branches also requires len(num_channels) == num_branches for every stage in extra; each parallel branch needs its own channel width. A mismatch raises ValueError naming NUM_CHANNELS.","triggerScenarios":"num_branches=3 with num_channels=[32,64] (len 2); editing HRNet width lists without adding an entry when adding a branch.","commonSituations":"Building custom HRNet-W48 variants; changing stage3/stage4 branch counts; miscounting after merging configs.","solutions":["Set num_channels to exactly num_branches entries, e.g. num_branches=3, num_channels=[48,96,192]","Keep width progression consistent with in_channels of the next stage","Prefer modifying pretrained official configs (w18/w32/w48) minimally"],"exampleFix":"# before\nstage3=dict(num_branches=3, num_channels=[32,64), num_blocks=[4,4,4])\n# after\nstage3=dict(num_branches=3, num_channels=[32,64,128], num_blocks=[4,4,4])","handlingStrategy":"validation","validationCode":"for stage in extra.values():\n    assert stage['num_branches'] == len(stage['num_channels']), 'num_channels length must equal num_branches'","typeGuard":"def channels_match(stage: dict) -> bool:\n    return stage['num_branches'] == len(stage['num_channels'])","tryCatchPattern":null,"preventionTips":["One channel width per branch","Keep widths aligned with in_channels of next stage","Use reference w18/w32/w48 settings"],"tags":["mmdet","hrnet","backbone","config-validation"],"backgroundTag":null,"analyzedSha":"cfd5d3a985b0249de009b67d04f37263e11cdf3d","analyzedAt":"2026-08-27T20:54:20.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}