{"record":{"id":"96d86419af06feb7","repo":"open-mmlab/mmdetection","slug":"metric-must-be-a-list-or-a-str","errorCode":null,"errorMessage":"metric must be a list or a str.","messagePattern":"metric must be a list or a str\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"mmdet/evaluation/metrics/mot_challenge_metric.py","lineNumber":104,"sourceCode":"                 format_only: bool = False,\n                 use_postprocess: bool = False,\n                 postprocess_tracklet_cfg: Optional[List[dict]] = [],\n                 collect_device: str = 'cpu',\n                 prefix: Optional[str] = None) -> None:\n        super().__init__(collect_device=collect_device, prefix=prefix)\n        if trackeval is None:\n            raise RuntimeError(\n                'trackeval is not installed,'\n                'please install it by: pip install'\n                'git+https://github.com/JonathonLuiten/TrackEval.git'\n                'trackeval need low version numpy, please install it'\n                'by: pip install -U numpy==1.23.5')\n        if isinstance(metric, list):\n            metrics = metric\n        elif isinstance(metric, str):\n            metrics = [metric]\n        else:\n            raise TypeError('metric must be a list or a str.')\n        for metric in metrics:\n            if metric not in self.allowed_metrics:\n                raise KeyError(f'metric {metric} is not supported.')\n        self.metrics = metrics\n        self.format_only = format_only\n        if self.format_only:\n            assert outfile_prefix is not None, 'outfile_prefix must be not'\n            'None when format_only is True, otherwise the result files will'\n            'be saved to a temp directory which will be cleaned up at the end.'\n        self.use_postprocess = use_postprocess\n        self.postprocess_tracklet_cfg = postprocess_tracklet_cfg.copy()\n        self.postprocess_tracklet_methods = [\n            TASK_UTILS.build(cfg) for cfg in self.postprocess_tracklet_cfg\n        ]\n        assert benchmark in self.allowed_benchmarks\n        self.benchmark = benchmark\n        self.track_iou_thr = track_iou_thr\n        self.tmp_dir = tempfile.TemporaryDirectory()","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/open-mmlab/mmdetection/blob/cfd5d3a985b0249de009b67d04f37263e11cdf3d/mmdet/evaluation/metrics/mot_challenge_metric.py#L86-L122","documentation":"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.","triggerScenarios":"Passing val_evaluator=dict(type='MOTChallengeMetric', metric=None) or metric=('mota',) (tuple) or an int/dict as the metric key in the config.","commonSituations":"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.","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"],"exampleFix":"// before\nval_evaluator=dict(type='MOTChallengeMetric', metric=None)\n// after\nval_evaluator=dict(type='MOTChallengeMetric', metric=['mota', 'idf1'])","handlingStrategy":"type-guard","validationCode":"assert isinstance(metric, (str, list)), \\\n    f'metric must be str or list, got {type(metric).__name__}'\nmetrics = [metric] if isinstance(metric, str) else list(metric)","typeGuard":"def is_valid_mot_metric_arg(metric) -> bool:\n    return isinstance(metric, str) or (isinstance(metric, list) and all(isinstance(m, str) for m in metric))","tryCatchPattern":"try:\n    m = MOTChallengeMetric(metric=metric)\nexcept TypeError as e:\n    if 'list or a str' in str(e):\n        metric = [metric] if isinstance(metric, str) else list(metric or [])\n        m = MOTChallengeMetric(metric=metric)\n    else:\n        raise","preventionTips":["Normalize metric to a list at config-build time","Validate templated config values are not None","Use lists (not tuples) in programmatic configs"],"tags":["mmdetection","tracking","mot","type-error","config"],"backgroundTag":"argument-type-validation","analyzedSha":"cfd5d3a985b0249de009b67d04f37263e11cdf3d","analyzedAt":"2026-08-27T20:54:20.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}