open-mmlab/mmdetection · error · TypeError

module must be a str or a list.

Error message

module must be a str or a list.

What it means

Raised by BaseMot.freeze_module when the `module` argument passed to freeze_module (or the `freeze_module` config field of a MOT model) is neither a str, list, nor tuple. The method resolves each entry with getattr(self, name) to set that submodule to eval mode and freeze its parameters, so the argument type must be one of the three supported container types.

Source

Thrown at mmdet/models/mot/base.py:36

        data_preprocessor (dict or ConfigDict, optional): The pre-process
           config of :class:`TrackDataPreprocessor`.  it usually includes,
            ``pad_size_divisor``, ``pad_value``, ``mean`` and ``std``.
        init_cfg (dict or list[dict]): Initialization config dict.
    """

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

    def freeze_module(self, module: Union[List[str], Tuple[str], str]) -> None:
        """Freeze module during training."""
        if isinstance(module, str):
            modules = [module]
        else:
            if not (isinstance(module, list) or isinstance(module, tuple)):
                raise TypeError('module must be a str or a list.')
            else:
                modules = module
        for module in modules:
            m = getattr(self, module)
            m.eval()
            for param in m.parameters():
                param.requires_grad = False

    @property
    def with_detector(self) -> bool:
        """bool: whether the framework has a detector."""
        return hasattr(self, 'detector') and self.detector is not None

    @property
    def with_reid(self) -> bool:
        """bool: whether the framework has a reid model."""
        return hasattr(self, 'reid') and self.reid is not None

View on GitHub (pinned to cfd5d3a985)

Solutions

  1. Set freeze_module to an attribute name string, e.g. freeze_module = 'detector', or a list of names, e.g. freeze_module = ['detector', 'reid']
  2. If you do not want to freeze anything, remove the freeze_module field from the config
  3. When calling programmatically, pass module names (str) matching nn.Module attributes of self

Example fix

# before
freeze_module = 2  # or {'detector'}
# after
freeze_module = ['detector']
Defensive patterns

Strategy: type-guard

Validate before calling

from typing import List, Tuple, Union
ok = isinstance(freeze, (str, list, tuple)) and all(isinstance(m, str) for m in (freeze if isinstance(freeze,(list,tuple)) else [freeze]))

Type guard

def is_valid_freeze_spec(v) -> bool:
    if isinstance(v, str): return True
    return isinstance(v, (list, tuple)) and len(v) > 0 and all(isinstance(x, str) for x in v)

Prevention

When it happens

Trigger: Setting `freeze_module=3` or a dict/None in a MOT (e.g. QDTrack/ByteTrack) config, or calling model.freeze_module({'detector'}) / freeze_module(None) directly.

Common situations: Copy-paste of a config where freeze_module was deleted leaving a wrong-typed value; YAML parsing a scalar that was meant to be a quoted attribute name; passing a detector module object instead of its attribute name string.

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/0e07474215ec57d9. Report an issue: GitHub.