{"record":{"id":"8023f443d3954ed4","repo":"open-mmlab/mmdetection","slug":"palette-does-not-match-classes-as-metainfo-is-sel","errorCode":null,"errorMessage":"palette does not match classes as metainfo is {self._metainfo}.","messagePattern":"palette does not match classes as metainfo is (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mmdet/datasets/base_semseg_dataset.py","lineNumber":224,"sourceCode":"            np.random.seed(42)\n            # random palette\n            new_palette = np.random.randint(\n                0, 255, size=(len(classes), 3)).tolist()\n            np.random.set_state(state)\n        elif len(palette) >= len(classes) and self.label_map is not None:\n            new_palette = []\n            # return subset of palette\n            for old_id, new_id in sorted(\n                    self.label_map.items(), key=lambda x: x[1]):\n                # 0 is background\n                if new_id != 0:\n                    new_palette.append(palette[old_id])\n            new_palette = type(palette)(new_palette)\n        elif len(palette) >= len(classes):\n            # Allow palette length is greater than classes.\n            return palette\n        else:\n            raise ValueError('palette does not match classes '\n                             f'as metainfo is {self._metainfo}.')\n        return new_palette\n\n    def load_data_list(self) -> List[dict]:\n        \"\"\"Load annotation from directory or annotation file.\n\n        Returns:\n            list[dict]: All data info of dataset.\n        \"\"\"\n        data_list = []\n        img_dir = self.data_prefix.get('img_path', None)\n        ann_dir = self.data_prefix.get('seg_map_path', None)\n        if not osp.isdir(self.ann_file) and self.ann_file:\n            assert osp.isfile(self.ann_file), \\\n                f'Failed to load `ann_file` {self.ann_file}'\n            lines = mmengine.list_from_file(\n                self.ann_file, backend_args=self.backend_args)\n            for line in lines:","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/open-mmlab/mmdetection/blob/cfd5d3a985b0249de009b67d04f37263e11cdf3d/mmdet/datasets/base_semseg_dataset.py#L206-L242","documentation":"BaseSemanticSegmentationDataset._update_palette validates the palette against metainfo classes after label mapping. A palette longer than classes is allowed (extra entries ignored after mapping), but a palette shorter than the (mapped) number of classes raises this ValueError showing the full metainfo. Palettes can be a list of RGB tuples or an mmcv ColorStatus-like string ('random'/'none'), and list palettes must cover the classes.","triggerScenarios":"Passing metainfo=dict(palette=[...]) with fewer color entries than the effective number of classes, e.g., a 3-color palette against a subset of 19 Cityscapes classes, or using a palette sized for the original dataset while classes were extended.","commonSituations":"Custom visualization configs copied between datasets with different class counts; palette lists with off-by-one lengths; using single-tuple palettes where a list-of-tuples is required.","solutions":["Set palette='random' (or omit it) to let the dataset generate colors automatically","Provide one RGB tuple per class: len(palette) >= len(classes) after label mapping — e.g., copy the 3-length list to the needed size or take a slice of mmcv's palette constants","If subsetting classes, also shrink/reorder the palette to match get_label_map semantics"],"exampleFix":"# before\nds = CityscapesDataset(...,\n  metainfo=dict(classes=['road', 'sidewalk', 'car'],\n                palette=[[128, 64, 128]]))  # 1 color for 3 classes\n# after\nds = CityscapesDataset(...,\n  metainfo=dict(classes=['road', 'sidewalk', 'car'],\n                palette=[[128, 64, 128], [244, 35, 232], [0, 0, 142]]))\n# or simply:\nds = CityscapesDataset(..., metainfo=dict(classes=[...], palette='random'))","handlingStrategy":"validation","validationCode":"n_classes = len(metainfo.get('classes', DatasetClass.METAINFO['classes']))\npal = metainfo.get('palette')\nif isinstance(pal, list):\n    assert len(pal) >= n_classes, f'palette has {len(pal)} colors for {n_classes} classes'","typeGuard":"def is_palette_valid(palette, n_classes) -> bool:\n    return not isinstance(palette, list) or len(palette) >= n_classes","tryCatchPattern":"try:\n    ds = DatasetClass(..., metainfo=metainfo)\nexcept ValueError as e:\n    if 'palette does not match classes' in str(e):\n        metainfo['palette'] = 'random'\n        ds = DatasetClass(..., metainfo=metainfo)\n    else:\n        raise","preventionTips":["Prefer palette='random' unless brand colors are required","Keep palette and classes lists in one metainfo dict so they are edited together, with a paired length test","When subsetting classes, regenerate the palette slice in the same commit"],"tags":["mmdetection","semantic-segmentation","palette","metainfo","visualization"],"backgroundTag":"length-mismatch-validation","analyzedSha":"cfd5d3a985b0249de009b67d04f37263e11cdf3d","analyzedAt":"2026-08-27T20:54:20.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}