open-mmlab/mmdetection · error · TypeError
metric must be a list or a str.
Error message
metric must be a list or a str.
What it means
MOTChallengeMetric.__init__ raises TypeError when the `metric` argument is neither a list nor a string. The evaluator accepts metric='mota' or metric=['mota','hota'] but any other type (dict, None, int) fails type validation before the per-metric check.
Source
Thrown at mmdet/evaluation/metrics/mot_challenge_metric.py:104
format_only: bool = False,
use_postprocess: bool = False,
postprocess_tracklet_cfg: Optional[List[dict]] = [],
collect_device: str = 'cpu',
prefix: Optional[str] = None) -> None:
super().__init__(collect_device=collect_device, prefix=prefix)
if trackeval is None:
raise RuntimeError(
'trackeval is not installed,'
'please install it by: pip install'
'git+https://github.com/JonathonLuiten/TrackEval.git'
'trackeval need low version numpy, please install it'
'by: pip install -U numpy==1.23.5')
if isinstance(metric, list):
metrics = metric
elif isinstance(metric, str):
metrics = [metric]
else:
raise TypeError('metric must be a list or a str.')
for metric in metrics:
if metric not in self.allowed_metrics:
raise KeyError(f'metric {metric} is not supported.')
self.metrics = metrics
self.format_only = format_only
if self.format_only:
assert outfile_prefix is not None, 'outfile_prefix must be not'
'None when format_only is True, otherwise the result files will'
'be saved to a temp directory which will be cleaned up at the end.'
self.use_postprocess = use_postprocess
self.postprocess_tracklet_cfg = postprocess_tracklet_cfg.copy()
self.postprocess_tracklet_methods = [
TASK_UTILS.build(cfg) for cfg in self.postprocess_tracklet_cfg
]
assert benchmark in self.allowed_benchmarks
self.benchmark = benchmark
self.track_iou_thr = track_iou_thr
self.tmp_dir = tempfile.TemporaryDirectory()View on GitHub (pinned to cfd5d3a985)
Solutions
- Set metric to a string or a list of strings, e.g. metric=['mota', 'idf1']
- Check the config variable producing metric for None values from templating/interpolation
- Prefer a list even for a single metric for consistency
Example fix
// before val_evaluator=dict(type='MOTChallengeMetric', metric=None) // after val_evaluator=dict(type='MOTChallengeMetric', metric=['mota', 'idf1'])
Defensive patterns
Strategy: type-guard
Validate before calling
assert isinstance(metric, (str, list)), \
f'metric must be str or list, got {type(metric).__name__}'
metrics = [metric] if isinstance(metric, str) else list(metric) Type guard
def is_valid_mot_metric_arg(metric) -> bool:
return isinstance(metric, str) or (isinstance(metric, list) and all(isinstance(m, str) for m in metric)) Try / catch
try:
m = MOTChallengeMetric(metric=metric)
except TypeError as e:
if 'list or a str' in str(e):
metric = [metric] if isinstance(metric, str) else list(metric or [])
m = MOTChallengeMetric(metric=metric)
else:
raise Prevention
- Normalize metric to a list at config-build time
- Validate templated config values are not None
- Use lists (not tuples) in programmatic configs
When it happens
Trigger: Passing val_evaluator=dict(type='MOTChallengeMetric', metric=None) or metric=('mota',) (tuple) or an int/dict as the metric key in the config.
Common situations: Config templating that injects None when a variable is undefined; using a tuple instead of a list in a Python-constructed config; YAML configs coercing an odd type for the metric field.
Related errors
- metric {metric} is not supported.
- module must be a str or a list.
- trackeval is not installed,please install it by: pip install
- The num_classes must be a current number, if there is cross
- LoadImageFromFile is not found in the test pipeline
AI-assisted analysis of open-mmlab/mmdetection@cfd5d3a985 (2026-08-27).
Data as JSON: /api/errors/96d86419af06feb7.
Report an issue: GitHub.