open-mmlab/mmdetection · warning

The `num_classes` should be 1 in RPN, but get {rpn_head_num_

Error message

The `num_classes` should be 1 in RPN, but get {rpn_head_num_classes}, please set rpn_head.num_classes = 1 in your config file.

What it means

TwoStageDetector constructor warns when the rpn_head config explicitly sets num_classes != 1, then forces it to 1 (None defaults silently to 1). Same rationale as RPN: the RPN head is class-agnostic.

Source

Thrown at mmdet/models/detectors/two_stage.py:48

                 data_preprocessor: OptConfigType = None,
                 init_cfg: OptMultiConfig = None) -> None:
        super().__init__(
            data_preprocessor=data_preprocessor, init_cfg=init_cfg)
        self.backbone = MODELS.build(backbone)

        if neck is not None:
            self.neck = MODELS.build(neck)

        if rpn_head is not None:
            rpn_train_cfg = train_cfg.rpn if train_cfg is not None else None
            rpn_head_ = rpn_head.copy()
            rpn_head_.update(train_cfg=rpn_train_cfg, test_cfg=test_cfg.rpn)
            rpn_head_num_classes = rpn_head_.get('num_classes', None)
            if rpn_head_num_classes is None:
                rpn_head_.update(num_classes=1)
            else:
                if rpn_head_num_classes != 1:
                    warnings.warn(
                        'The `num_classes` should be 1 in RPN, but get '
                        f'{rpn_head_num_classes}, please set '
                        'rpn_head.num_classes = 1 in your config file.')
                    rpn_head_.update(num_classes=1)
            self.rpn_head = MODELS.build(rpn_head_)

        if roi_head is not None:
            # update train and test cfg here for now
            # TODO: refactor assigner & sampler
            rcnn_train_cfg = train_cfg.rcnn if train_cfg is not None else None
            roi_head.update(train_cfg=rcnn_train_cfg)
            roi_head.update(test_cfg=test_cfg.rcnn)
            self.roi_head = MODELS.build(roi_head)

        self.train_cfg = train_cfg
        self.test_cfg = test_cfg

    def _load_from_state_dict(self, state_dict: dict, prefix: str,

View on GitHub (pinned to cfd5d3a985)

Solutions

  1. Change or remove rpn_head.num_classes so it equals 1
  2. Put per-dataset num_classes only in roi_head.bbox_head

Example fix

# before
rpn_head=dict(type='RPNHead', num_classes=80, ...)
# after
rpn_head=dict(type='RPNHead', ...)  # num_classes defaults to 1
Defensive patterns

Strategy: validation

Validate before calling

rpn = cfg['model'].get('rpn_head')
if rpn is not None:
    rpn['num_classes'] = 1

Prevention

When it happens

Trigger: Building a two-stage detector (Faster/Mask R-CNN etc.) whose rpn_head dict contains num_classes != 1.

Common situations: Config edits where a bbox_head's num_classes was duplicated into rpn_head; configs migrated from tutorials with wrong rpn settings.

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


AI-assisted analysis of open-mmlab/mmdetection@cfd5d3a985 (2026-08-27). Data as JSON: /api/errors/4295be16e5509296. Report an issue: GitHub.