{"record":{"id":"13be58e12d78df03","repo":"roboflow/supervision","slug":"labelme-polygon-shape-label-label-has-len-poi","errorCode":null,"errorMessage":"LabelMe polygon shape (label={label}) has {len(points)} point(s); expected at least 3.","messagePattern":"LabelMe polygon shape \\(label=(.+?)\\) has (.+?) point\\(s\\); expected at least 3\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/dataset/formats/labelme.py","lineNumber":127,"sourceCode":"            )\n        points = np.array(points_raw, dtype=np.float32)\n        if points.ndim != 2 or points.shape[1] != 2:\n            raise ValueError(\n                f\"LabelMe shape of type {shape_type!r} (label={label!r}) has \"\n                f\"malformed points: expected an (N, 2) array, got shape \"\n                f\"{points.shape}.\"\n            )\n        if shape_type == \"rectangle\":\n            if len(points) < 2:\n                raise ValueError(\n                    f\"LabelMe rectangle shape (label={label!r}) has \"\n                    f\"{len(points)} point(s); expected at least 2.\"\n                )\n            xyxy = _rectangle_to_xyxy(points)\n            polygon = _xyxy_to_polygon(xyxy)\n        else:\n            if len(points) < 3:\n                raise ValueError(\n                    f\"LabelMe polygon shape (label={label!r}) has \"\n                    f\"{len(points)} point(s); expected at least 3.\"\n                )\n            xyxy = polygon_to_xyxy(polygon=points).astype(np.float32)\n            polygon = points\n        xyxy_list.append(xyxy)\n        class_ids.append(class_to_index[label])\n        if with_masks:\n            polygons.append(polygon)\n\n    if skipped_types:\n        warnings.warn(\n            f\"Skipped unsupported LabelMe shape type(s) {sorted(skipped_types)}; \"\n            f\"only {list(SUPPORTED_SHAPE_TYPES)} are imported.\",\n            UserWarning,\n            stacklevel=2,\n        )\n","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/dataset/formats/labelme.py#L109-L145","documentation":"Raised by the LabelMe dataset loader when a non-rectangle shape (polygon, linestrip-like types treated as polygons) contains fewer than 3 points. A polygon needs at least 3 vertices to enclose an area and be converted to a bounding box, so the loader refuses to convert it. The offending shape's label is included in the message to help locate it in the JSON annotation file.","triggerScenarios":"Loading a LabelMe dataset (DetectionDataset.from_labelme or the labelme format module) where a shapes[] entry with shape_type other than 'rectangle' has a points array of length 0, 1, or 2. Happens with hand-drawn annotations, corrupted files, or exports from tools that emit degenerate polygons.","commonSituations":"Manually annotated datasets where a shape was started but not finished; third-party converters that emit empty points arrays; JSON edits that truncated points; linestrip shapes (2 points) being treated as polygons.","solutions":["Open the LabelMe JSON file named in the surrounding error context and find the shape with the reported label; add a third point or delete the shape.","If the shape was meant to be a line, either convert it to shape_type 'rectangle' with 2 diagonal points or filter it out before loading.","Write a small pre-processing pass over the dataset that drops or repairs shapes with len(points) < 3 before calling the loader.","Regenerate the annotation from the source tool (e.g. re-draw in LabelMe) if the file is corrupted."],"exampleFix":"// before (labelme JSON)\n{\"label\": \"door\", \"shape_type\": \"polygon\", \"points\": [[10, 10], [40, 10]]}\n\n// after\n{\"label\": \"door\", \"shape_type\": \"polygon\", \"points\": [[10, 10], [40, 10], [40, 40]]}","handlingStrategy":"validation","validationCode":"import json\n\ndef valid_labelme_shapes(path):\n    with open(path) as f:\n        data = json.load(f)\n    for shape in data.get(\"shapes\", []):\n        pts = shape.get(\"points\", [])\n        if shape.get(\"shape_type\") == \"rectangle\":\n            if len(pts) < 2:\n                return False\n        elif len(pts) < 3:\n            return False\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    ds = sv.DetectionDataset.from_labelme(...)\nexcept ValueError as e:\n    if \"expected at least 3\" in str(e):\n        log.warning(\"skipping malformed annotation: %s\", e)\n    else:\n        raise","preventionTips":["Run a dataset lint pass that flags shapes with fewer points than their shape_type requires before loading.","Prefer re-exporting from the LabelMe tool rather than hand-editing points arrays.","In CI for annotation datasets, assert every shape has >= 3 points (>= 2 for rectangles)."],"tags":["labelme","dataset","annotation","polygon","validation"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}