{"record":{"id":"a5b3d40bc2b22ac9","repo":"facebookresearch/detectron2","slug":"unknown-geometric-structure","errorCode":null,"errorMessage":"Unknown geometric structure {}","messagePattern":"Unknown geometric structure (.+?)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"detectron2/data/datasets/cityscapes.py","lineNumber":215,"sourceCode":"                polygons_union = polygons_union.union(poly)\n                continue\n\n            # Take non-overlapping part of the polygon\n            poly_wo_overlaps = poly.difference(polygons_union)\n            if poly_wo_overlaps.is_empty:\n                continue\n            polygons_union = polygons_union.union(poly)\n\n            anno = {}\n            anno[\"iscrowd\"] = label_name.endswith(\"group\")\n            anno[\"category_id\"] = label.id\n\n            if isinstance(poly_wo_overlaps, Polygon):\n                poly_list = [poly_wo_overlaps]\n            elif isinstance(poly_wo_overlaps, MultiPolygon):\n                poly_list = poly_wo_overlaps.geoms\n            else:\n                raise NotImplementedError(\"Unknown geometric structure {}\".format(poly_wo_overlaps))\n\n            poly_coord = []\n            for poly_el in poly_list:\n                # COCO API can work only with exterior boundaries now, hence we store only them.\n                # TODO: store both exterior and interior boundaries once other parts of the\n                # codebase support holes in polygons.\n                poly_coord.append(list(chain(*poly_el.exterior.coords)))\n            anno[\"segmentation\"] = poly_coord\n            (xmin, ymin, xmax, ymax) = poly_wo_overlaps.bounds\n\n            anno[\"bbox\"] = (xmin, ymin, xmax, ymax)\n            anno[\"bbox_mode\"] = BoxMode.XYXY_ABS\n\n            annos.append(anno)\n    else:\n        # See also the official annotation parsing scripts at\n        # https://github.com/mcordts/cityscapesScripts/blob/master/cityscapesscripts/evaluation/instances2dict.py  # noqa\n        with PathManager.open(instance_id_file, \"rb\") as f:","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/facebookresearch/detectron2/blob/a2f4a8771ab77e8411c26b27f24f9489a28a2453/detectron2/data/datasets/cityscapes.py#L197-L233","documentation":"While converting Cityscapes annotation polygons, shapely's difference/union produced an object that is neither Polygon nor MultiPolygon (e.g. GeometryCollection containing lines/points, or empty geometry). The converter cannot turn it into COCO polygon lists, so it raises NotImplementedError.","triggerScenarios":"Loading Cityscapes labels via _cityscapes_files_to_dict on an image whose instance polygons, after overlap removal, degenerate into a GeometryCollection or empty geometry (tiny/degenerate masks, self-intersecting or sliver polygons).","commonSituations":"Corrupted or manually edited Cityscapes label files; annotations with near-zero-area or overlapping degenerate polygons; shapely version behavior differences producing GeometryCollection from difference().","solutions":["Fix or regenerate the offending *_polygons.json annotation file (inspect which image id fails from the traceback)","Upgrade/downgrade detectron2 — later versions handle GeometryCollection and filter degenerate parts","Preprocess: filter out annotations whose polygon difference yields empty or non-polygonal geometry before conversion"],"exampleFix":"// before\npoly_wo_overlaps = polys[i].difference(offsetcrowns_union)\n// after (defensive)\nif isinstance(poly_wo_overlaps, (Polygon, MultiPolygon)) and not poly_wo_overlaps.is_empty:\n    ...proceed...\nelse:\n    continue  # skip degenerate annotation","handlingStrategy":"validation","validationCode":"from shapely.geometry import Polygon, MultiPolygon\nok = isinstance(poly_wo_overlaps, (Polygon, MultiPolygon)) and not poly_wo_overlaps.is_empty","typeGuard":"def is_convertible_polygon(g) -> bool:\n    return (isinstance(g, (Polygon, MultiPolygon))\n            and not g.is_empty\n            and g.area > 0)","tryCatchPattern":"try:\n    dicts = _cityscapes_files_to_dict(...)\nexcept NotImplementedError as e:\n    log.warning(f'skipping malformed cityscapes file: {e}')","preventionTips":["Validate label polygon files with shapely before dataset conversion","Keep shapely/detectron2 versions in sync; newer versions handle GeometryCollection","Backup and verify Cityscapes json labels after any manual edits"],"tags":["detectron2","cityscapes","shapely","polygon-conversion"],"backgroundTag":"invalid-geometry-shape","analyzedSha":"a2f4a8771ab77e8411c26b27f24f9489a28a2453","analyzedAt":"2026-08-27T12:08:21.260Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}