{"record":{"id":"3fa47b74e5355810","repo":"open-mmlab/mmdetection","slug":"num-classes-num-classes-is-too-small","errorCode":null,"errorMessage":"num_classes={num_classes} is too small","messagePattern":"num_classes=(.+?) is too small","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mmdet/models/dense_heads/anchor_head.py","lineNumber":80,"sourceCode":"        loss_bbox: ConfigType = dict(\n            type='SmoothL1Loss', beta=1.0 / 9.0, loss_weight=1.0),\n        train_cfg: OptConfigType = None,\n        test_cfg: OptConfigType = None,\n        init_cfg: OptMultiConfig = dict(\n            type='Normal', layer='Conv2d', std=0.01)\n    ) -> None:\n        super().__init__(init_cfg=init_cfg)\n        self.in_channels = in_channels\n        self.num_classes = num_classes\n        self.feat_channels = feat_channels\n        self.use_sigmoid_cls = loss_cls.get('use_sigmoid', False)\n        if self.use_sigmoid_cls:\n            self.cls_out_channels = num_classes\n        else:\n            self.cls_out_channels = num_classes + 1\n\n        if self.cls_out_channels <= 0:\n            raise ValueError(f'num_classes={num_classes} is too small')\n        self.reg_decoded_bbox = reg_decoded_bbox\n\n        self.bbox_coder = TASK_UTILS.build(bbox_coder)\n        self.loss_cls = MODELS.build(loss_cls)\n        self.loss_bbox = MODELS.build(loss_bbox)\n        self.train_cfg = train_cfg\n        self.test_cfg = test_cfg\n        if self.train_cfg:\n            self.assigner = TASK_UTILS.build(self.train_cfg['assigner'])\n            if train_cfg.get('sampler', None) is not None:\n                self.sampler = TASK_UTILS.build(\n                    self.train_cfg['sampler'], default_args=dict(context=self))\n            else:\n                self.sampler = PseudoSampler(context=self)\n\n        self.fp16_enabled = False\n\n        self.prior_generator = TASK_UTILS.build(anchor_generator)","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/open-mmlab/mmdetection/blob/cfd5d3a985b0249de009b67d04f37263e11cdf3d/mmdet/models/dense_heads/anchor_head.py#L62-L98","documentation":"AnchorHead.__init__ computes cls_out_channels (num_classes with sigmoid, num_classes+1 with softmax) and raises ValueError if it is <= 0. With sigmoid classification num_classes=0 yields 0 channels, which is invalid for a detection head.","triggerScenarios":"AnchorHead(num_classes=0) with use_sigmoid_cls=True; passing a negative num_classes; configs where num_classes was left at default or overwritten by mistake.","commonSituations":"Copying a class-agnostic head config with num_classes=0; config inheritance overriding num_classes to 0; changing use_sigmoid_cls without adjusting num_classes semantics.","solutions":["Set num_classes to the real number of foreground classes (>=1)","If using softmax classification (use_sigmoid_cls=False), remember background adds +1, but num_classes itself must still be positive","Check config inheritance chains for num_classes=0 overrides"],"exampleFix":"// before\nbbox_head=dict(type='AnchorHead', num_classes=0, use_sigmoid_cls=True)\n// after\nbbox_head=dict(type='AnchorHead', num_classes=80, use_sigmoid_cls=True)","handlingStrategy":"validation","validationCode":"effective = num_classes if use_sigmoid_cls else num_classes + 1\\nassert effective > 0, 'num_classes must be positive'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate num_classes after config inheritance","Never use num_classes=0 with sigmoid classification"],"tags":["mmdet","anchor-head","num-classes","config","validation"],"backgroundTag":"invalid-config-value","analyzedSha":"cfd5d3a985b0249de009b67d04f37263e11cdf3d","analyzedAt":"2026-08-27T20:54:20.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}