open-mmlab/mmdetection · warning · UserWarning

config is now expected to have a `runner` section, please se

Error message

config is now expected to have a `runner` section, please set `runner` in your config.

What it means

compat_runner_args in mmdet/utils/compat_config.py fires when a config lacks a runner section but still carries the MMDet V1.x-style total_epochs key. It auto-creates cfg.runner = {'type': 'EpochBasedRunner', 'max_epochs': total_epochs} so training proceeds, then warns that configs are expected to declare runner explicitly in V2.x style.

Source

Thrown at mmdet/utils/compat_config.py:28

    config.

    For example, it will move some args which will be deprecated to the correct
    fields.
    """
    cfg = copy.deepcopy(cfg)
    cfg = compat_imgs_per_gpu(cfg)
    cfg = compat_loader_args(cfg)
    cfg = compat_runner_args(cfg)
    return cfg


def compat_runner_args(cfg):
    if 'runner' not in cfg:
        cfg.runner = ConfigDict({
            'type': 'EpochBasedRunner',
            'max_epochs': cfg.total_epochs
        })
        warnings.warn(
            'config is now expected to have a `runner` section, '
            'please set `runner` in your config.', UserWarning)
    else:
        if 'total_epochs' in cfg:
            assert cfg.total_epochs == cfg.runner.max_epochs
    return cfg


def compat_imgs_per_gpu(cfg):
    cfg = copy.deepcopy(cfg)
    if 'imgs_per_gpu' in cfg.data:
        warnings.warn('"imgs_per_gpu" is deprecated in MMDet V2.0. '
                      'Please use "samples_per_gpu" instead')
        if 'samples_per_gpu' in cfg.data:
            warnings.warn(
                f'Got "imgs_per_gpu"={cfg.data.imgs_per_gpu} and '
                f'"samples_per_gpu"={cfg.data.samples_per_gpu}, "imgs_per_gpu"'
                f'={cfg.data.imgs_per_gpu} is used in this experiments')

View on GitHub (pinned to cfd5d3a985)

Solutions

  1. Replace total_epochs = 12 in your config with runner = dict(type='EpochBasedRunner', max_epochs=12).
  2. If you must keep total_epochs for compat, also set runner with a matching max_epochs so the assert passes.
  3. For IterBasedRunner-style training use runner = dict(type='IterBasedRunner', max_iters=...) and keep total_epochs out of the config.
  4. Re-run compat_cfg() after edits to confirm the warning disappears.

Example fix

# before
total_epochs = 12
# after
runner = dict(type='EpochBasedRunner', max_epochs=12)
Defensive patterns

Strategy: validation

Validate before calling

from mmcv import Config

def check_runner(cfg: Config) -> Config:
    if 'runner' not in cfg:
        cfg.runner = dict(type='EpochBasedRunner', max_epochs=cfg.get('total_epochs', 12))
    cfg.pop('total_epochs', None)
    return cfg

Prevention

When it happens

Trigger: Running a training entrypoint (tools/train.py) or any code path that calls compat_cfg(cfg) with a config that defines total_epochs=N but no runner=dict(...) block. The assert branch fires instead if both exist and disagree: assert cfg.total_epochs == cfg.runner.max_epochs.

Common situations: Porting old MMDet V1.x configs or community configs to V2.x; upgrading mmdetection versions where runner was introduced; copy-pasting a legacy config into a newer install.

Related errors


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