{"record":{"id":"ac5a0828ba65d265","repo":"facebookresearch/detectron2","slug":"cannot-create-polygonmasks-expect-a-list-of-list","errorCode":null,"errorMessage":"Cannot create PolygonMasks: Expect a list of list of polygons per image. Got '{}' instead.","messagePattern":"Cannot create PolygonMasks: Expect a list of list of polygons per image\\. Got '(.+?)' instead\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"detectron2/structures/masks.py","lineNumber":282,"sourceCode":"    \"\"\"\n    This class stores the segmentation masks for all objects in one image, in the form of polygons.\n\n    Attributes:\n        polygons: list[list[ndarray]]. Each ndarray is a float64 vector representing a polygon.\n    \"\"\"\n\n    def __init__(self, polygons: List[List[Union[torch.Tensor, np.ndarray]]]):\n        \"\"\"\n        Arguments:\n            polygons (list[list[np.ndarray]]): The first\n                level of the list correspond to individual instances,\n                the second level to all the polygons that compose the\n                instance, and the third level to the polygon coordinates.\n                The third level array should have the format of\n                [x0, y0, x1, y1, ..., xn, yn] (n >= 3).\n        \"\"\"\n        if not isinstance(polygons, list):\n            raise ValueError(\n                \"Cannot create PolygonMasks: Expect a list of list of polygons per image. \"\n                \"Got '{}' instead.\".format(type(polygons))\n            )\n\n        def _make_array(t: Union[torch.Tensor, np.ndarray]) -> np.ndarray:\n            # Use float64 for higher precision, because why not?\n            # Always put polygons on CPU (self.to is a no-op) since they\n            # are supposed to be small tensors.\n            # May need to change this assumption if GPU placement becomes useful\n            if isinstance(t, torch.Tensor):\n                t = t.cpu().numpy()\n            return np.asarray(t).astype(\"float64\")\n\n        def process_polygons(\n            polygons_per_instance: List[Union[torch.Tensor, np.ndarray]],\n        ) -> List[np.ndarray]:\n            if not isinstance(polygons_per_instance, list):\n                raise ValueError(","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/facebookresearch/detectron2/blob/a2f4a8771ab77e8411c26b27f24f9489a28a2453/detectron2/structures/masks.py#L264-L300","documentation":"PolygonMasks expects a 3-level list structure: per image a list of instances, each a list of polygon arrays. Passing a numpy array, tensor, or flattened list of polygons at the top level fails the isinstance(polygons, list) check.","triggerScenarios":"PolygonMasks(np.array([...])) or PolygonMasks([poly1, poly2]) instead of PolygonMasks([[poly1, poly2]]); converting from COCO anns without grouping per image.","commonSituations":"Loading DOTA/COCO-style annotations and passing polygons directly instead of the per-image nested list; version-0-era code relying on looser inputs.","solutions":["Wrap polygons per image: PolygonMasks([[poly1, poly2], [poly3]]) — outer list per image, inner list per instance","Build from dataset dicts via detectron2's detected already-nested structures","Convert numpy/tensor inputs to the nested list form first"],"exampleFix":"# before\nmasks = PolygonMasks(np.array([poly1, poly2]))\n# after\nmasks = PolygonMasks([[poly1, poly2]])","handlingStrategy":"validation","validationCode":"assert isinstance(polygons, list) and all(isinstance(img, list) for img in polygons), 'PolygonMasks expects list[list[polygon-array]]'","typeGuard":"def is_valid_polygon_list(p) -> bool:\n    return isinstance(p, list) and all(isinstance(inst, list) for inst in p)","tryCatchPattern":"try:\n    masks = PolygonMasks(polygons)\nexcept ValueError as e:\n    raise ValueError(f'Bad polygon structure: {e}') from e","preventionTips":["Normalize annotations to 3-level nesting before PolygonMasks","Write dataset adapter tests with sample annotations"],"tags":["detectron2","polygon-masks","annotation-format"],"backgroundTag":"invalid-data-structure-format","analyzedSha":"a2f4a8771ab77e8411c26b27f24f9489a28a2453","analyzedAt":"2026-08-27T12:08:21.260Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}