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
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.
Source
Thrown at mmdet/evaluation/metrics/reid_metric.py:43
If prefix is not provided in the argument, self.default_prefix
will be used instead. Default: None
"""
allowed_metrics = ['mAP', 'CMC']
default_prefix: Optional[str] = 'reid-metric'
def __init__(self,
metric: Union[str, Sequence[str]] = 'mAP',
metric_options: Optional[dict] = None,
collect_device: str = 'cpu',
prefix: Optional[str] = None) -> None:
super().__init__(collect_device, prefix)
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.metric_options = metric_options or dict(
rank_list=[1, 5, 10, 20], max_rank=20)
for rank in self.metric_options['rank_list']:
assert 1 <= rank <= self.metric_options['max_rank']
def process(self, data_batch: dict, data_samples: Sequence[dict]) -> None:
"""Process one batch of data samples and predictions.
The processed results should be stored in ``self.results``, which will
be used to compute the metrics when all batches have been processed.
Args:
data_batch (dict): A batch of data from the dataloader.View on GitHub (pinned to cfd5d3a985)
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)
Example fix
# before
val_evaluator = dict(type='ReIDMetrics', metric=('mAP', 'CMC'))
# after
val_evaluator = dict(type='ReIDMetrics', metric=['mAP', 'CMC']) Defensive patterns
Strategy: type-guard
Validate before calling
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]'
Type guard
def is_valid_metric_arg(metric) -> bool:
if isinstance(metric, str): return True
return isinstance(metric, list) and all(isinstance(m, str) for m in metric) Try / catch
try:
m = ReIDMetrics(metric=metric)
except TypeError:
metric = list(metric) if isinstance(metric, (list, tuple)) else [str(metric)]
m = ReIDMetrics(metric=metric) Prevention
- Always write metric as str or list[str] in configs
- Validate config values before building evaluators
- Avoid tuples/dicts for metric args
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- The type of frame_range must be int or list.
- metric {metric} is not supported.
- metrics {iou_metrics} is not supported. Only supports mIoU/m
- out_indices must be a subset of range(0, 8). But received {o
- Expect "arch" to be either a string or a dict, got {type(arc
AI-assisted analysis of open-mmlab/mmdetection@cfd5d3a985 (2026-08-27).
Data as JSON: /api/errors/345d8764c9d8be6a.
Report an issue: GitHub.