open-mmlab/mmdetection · error · ValueError
num_classes={num_classes} is too small
Error message
num_classes={num_classes} is too small What it means
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.
Source
Thrown at mmdet/models/dense_heads/anchor_head.py:80
loss_bbox: ConfigType = dict(
type='SmoothL1Loss', beta=1.0 / 9.0, loss_weight=1.0),
train_cfg: OptConfigType = None,
test_cfg: OptConfigType = None,
init_cfg: OptMultiConfig = dict(
type='Normal', layer='Conv2d', std=0.01)
) -> None:
super().__init__(init_cfg=init_cfg)
self.in_channels = in_channels
self.num_classes = num_classes
self.feat_channels = feat_channels
self.use_sigmoid_cls = loss_cls.get('use_sigmoid', False)
if self.use_sigmoid_cls:
self.cls_out_channels = num_classes
else:
self.cls_out_channels = num_classes + 1
if self.cls_out_channels <= 0:
raise ValueError(f'num_classes={num_classes} is too small')
self.reg_decoded_bbox = reg_decoded_bbox
self.bbox_coder = TASK_UTILS.build(bbox_coder)
self.loss_cls = MODELS.build(loss_cls)
self.loss_bbox = MODELS.build(loss_bbox)
self.train_cfg = train_cfg
self.test_cfg = test_cfg
if self.train_cfg:
self.assigner = TASK_UTILS.build(self.train_cfg['assigner'])
if train_cfg.get('sampler', None) is not None:
self.sampler = TASK_UTILS.build(
self.train_cfg['sampler'], default_args=dict(context=self))
else:
self.sampler = PseudoSampler(context=self)
self.fp16_enabled = False
self.prior_generator = TASK_UTILS.build(anchor_generator)View on GitHub (pinned to cfd5d3a985)
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
Example fix
// before bbox_head=dict(type='AnchorHead', num_classes=0, use_sigmoid_cls=True) // after bbox_head=dict(type='AnchorHead', num_classes=80, use_sigmoid_cls=True)
Defensive patterns
Strategy: validation
Validate before calling
effective = num_classes if use_sigmoid_cls else num_classes + 1\nassert effective > 0, 'num_classes must be positive'
Prevention
- Validate num_classes after config inheritance
- Never use num_classes=0 with sigmoid classification
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- metric must be a list or a str.
- metrics {iou_metrics} is not supported. Only supports mIoU/m
- out_indices must be a subset of range(0, 8). But received {o
- Expect "arch" to be either a string or a dict, got {type(arc
- Invalid text mode "{self.text_mode}".
AI-assisted analysis of open-mmlab/mmdetection@cfd5d3a985 (2026-08-27).
Data as JSON: /api/errors/3fa47b74e5355810.
Report an issue: GitHub.