open-mmlab/mmdetection · error · ValueError
dataset metainfo must contain `classes`
Error message
dataset metainfo must contain `classes`
What it means
ClassAwareSampler builds a category-to-image index by reading dataset.metainfo['classes']; if the wrapped dataset has no 'classes' key in its metainfo (e.g. it is a plain base dataset or a wrapper that drops metainfo), sampling cannot proceed and ValueError is raised during __init__.
Source
Thrown at mmdet/datasets/samplers/class_aware_sampler.py:80
# get number of images containing each category
self.num_cat_imgs = [len(x) for x in self.cat_dict.values()]
# filter labels without images
self.valid_cat_inds = [
i for i, length in enumerate(self.num_cat_imgs) if length != 0
]
self.num_classes = len(self.valid_cat_inds)
def get_cat2imgs(self) -> Dict[int, list]:
"""Get a dict with class as key and img_ids as values.
Returns:
dict[int, list]: A dict of per-label image list,
the item of the dict indicates a label index,
corresponds to the image index that contains the label.
"""
classes = self.dataset.metainfo.get('classes', None)
if classes is None:
raise ValueError('dataset metainfo must contain `classes`')
# sort the label index
cat2imgs = {i: [] for i in range(len(classes))}
for i in range(len(self.dataset)):
cat_ids = set(self.dataset.get_cat_ids(i))
for cat in cat_ids:
cat2imgs[cat].append(i)
return cat2imgs
def __iter__(self) -> Iterator[int]:
# deterministically shuffle based on epoch
g = torch.Generator()
g.manual_seed(self.epoch + self.seed)
# initialize label list
label_iter_list = RandomCycleIter(self.valid_cat_inds, generator=g)
# initialize each per-label image list
data_iter_dict = dict()
for i in self.valid_cat_inds:View on GitHub (pinned to cfd5d3a985)
Solutions
- Give the dataset a metainfo containing classes, e.g. metainfo=dict(classes=...) or define METAINFO in your dataset subclass using mmdet's CocoDetClasses
- Ensure the sampler wraps the leaf detection dataset (like CocoDataset) rather than a wrapper that strips metainfo
- Pass metainfo explicitly through the dataset config: dataset=dict(type='MyDataset', metainfo=dict(classes=[...]), ...)
Example fix
# before dataset = dict(type='MyDetDataset', ...) # no classes in metainfo sampler = dict(type='ClassAwareSampler', num_sample_class=1, cls_loss_weight=1.0) # after from mmdet.datasets import CocoDetClasses dataset = dict(type='MyDetDataset', metainfo=dict(classes=CocoDetClasses), ...)
Defensive patterns
Strategy: validation
Validate before calling
metainfo = dataset.metainfo assert 'classes' in metainfo and metainfo['classes'], 'dataset metainfo lacks classes; required by ClassAwareSampler'
Type guard
def has_classes_metainfo(ds) -> bool:
return bool(getattr(ds, 'metainfo', {}).get('classes')) Prevention
- Always define METAINFO (with classes) in custom detection dataset classes
- Pass metainfo=dict(classes=...) explicitly when wrapping generic datasets with ClassAwareSampler
When it happens
Trigger: Constructing ClassAwareSampler over a dataset whose METAINFO lacks 'classes' — e.g. wrapping ConcatDataset/CustomDataset without category definitions, a video/tracking dataset, or a plain mmengine BaseDataset with no metainfo merge.
Common situations: Using ClassAwareSampler with a custom dataset class that forgets to define METAINFO with classes, wrapping datasets in ClassBalancedDataset (double wrapping) that hides metainfo, or version upgrades where metainfo propagation changed.
Related errors
- new classes {new_classes} is not a subset of classes {old_cl
- sampler should be an instance of ``Sampler``, but got {sampl
- batch_size should be a positive integer value, but got batch
- DETR do not build sampler.
- palette does not match classes as metainfo is {self._metainf
AI-assisted analysis of open-mmlab/mmdetection@cfd5d3a985 (2026-08-27).
Data as JSON: /api/errors/d4976e626afae685.
Report an issue: GitHub.