{"record":{"id":"345d8764c9d8be6a","repo":"open-mmlab/mmdetection","slug":"metric-must-be-a-list-or-a-str-345d87","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/reid_metric.py","lineNumber":43,"sourceCode":"            If prefix is not provided in the argument, self.default_prefix\n            will be used instead. Default: None\n    \"\"\"\n    allowed_metrics = ['mAP', 'CMC']\n    default_prefix: Optional[str] = 'reid-metric'\n\n    def __init__(self,\n                 metric: Union[str, Sequence[str]] = 'mAP',\n                 metric_options: Optional[dict] = None,\n                 collect_device: str = 'cpu',\n                 prefix: Optional[str] = None) -> None:\n        super().__init__(collect_device, prefix)\n\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\n        self.metric_options = metric_options or dict(\n            rank_list=[1, 5, 10, 20], max_rank=20)\n        for rank in self.metric_options['rank_list']:\n            assert 1 <= rank <= self.metric_options['max_rank']\n\n    def process(self, data_batch: dict, data_samples: Sequence[dict]) -> None:\n        \"\"\"Process one batch of data samples and predictions.\n\n        The processed results should be stored in ``self.results``, which will\n        be used to compute the metrics when all batches have been processed.\n\n        Args:\n            data_batch (dict): A batch of data from the dataloader.","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/open-mmlab/mmdetection/blob/cfd5d3a985b0249de009b67d04f37263e11cdf3d/mmdet/evaluation/metrics/reid_metric.py#L25-L61","documentation":"ReIDMetrics.__init__ only accepts metric as a list of strings or a single string; any other type (int, None, tuple, dict) raises this TypeError before any evaluation starts. It is a configuration-type guard on the constructor argument.","triggerScenarios":"Passing metric=None, metric=('mAP','CMC'), metric=1, or an unhashable/other object to ReIDMetrics; also a config file where the metric key resolves to a non-str value.","commonSituations":"YAML/Python config typo like metric: [mAP, CMC] being fine but metric: {mAP: CMC} failing; passing a generator or numpy array; older configs passing tuples.","solutions":["Pass metric as a string, e.g. metric='mAP', or a list of strings, e.g. metric=['mAP','CMC']","Check the config value resolves to str or list[str] before constructing the metric","If loading configs dynamically, coerce: metric = list(metric) if isinstance(metric,(list,tuple)) else str(metric)"],"exampleFix":"# before\nval_evaluator = dict(type='ReIDMetrics', metric=('mAP', 'CMC'))\n# after\nval_evaluator = dict(type='ReIDMetrics', metric=['mAP', 'CMC'])","handlingStrategy":"type-guard","validationCode":"assert isinstance(metric, (str, list)) and all(isinstance(m, str) for m in (metric if isinstance(metric, list) else [metric])), 'metric must be str or list[str]'","typeGuard":"def is_valid_metric_arg(metric) -> bool:\n    if isinstance(metric, str): return True\n    return isinstance(metric, list) and all(isinstance(m, str) for m in metric)","tryCatchPattern":"try:\n    m = ReIDMetrics(metric=metric)\nexcept TypeError:\n    metric = list(metric) if isinstance(metric, (list, tuple)) else [str(metric)]\n    m = ReIDMetrics(metric=metric)","preventionTips":["Always write metric as str or list[str] in configs","Validate config values before building evaluators","Avoid tuples/dicts for metric args"],"tags":["mmdet","reid","typeerror","config","validation"],"backgroundTag":null,"analyzedSha":"cfd5d3a985b0249de009b67d04f37263e11cdf3d","analyzedAt":"2026-08-27T20:54:20.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}