{"record":{"id":"4bd5abdd1410e336","repo":"roboflow/supervision","slug":"no-labels-defined-for-class-id-class-id","errorCode":null,"errorMessage":"No labels defined for class_id={class_id}.","messagePattern":"No labels defined for class_id=(.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/key_points/annotators.py","lineNumber":969,"sourceCode":"    @staticmethod\n    def _resolve_labels(\n        labels: list[str] | dict[int, list[str]] | None,\n        points_count: int,\n        class_id: int | None = None,\n    ) -> list[str]:\n        \"\"\"Return the label list for a single instance.\"\"\"\n        if labels is None:\n            return [str(j) for j in range(points_count)]\n\n        resolved: list[str]\n        if isinstance(labels, dict):\n            if class_id is None:\n                raise ValueError(\n                    \"labels is a dict but class_id is None; \"\n                    \"KeyPoints must have class_id set.\"\n                )\n            if class_id not in labels:\n                raise ValueError(f\"No labels defined for class_id={class_id}.\")\n            resolved = labels[class_id]\n        else:\n            resolved = labels\n\n        if len(resolved) != points_count:\n            raise ValueError(\n                f\"Number of labels ({len(resolved)}) must match \"\n                f\"number of key points ({points_count}).\"\n            )\n        return resolved\n\n    @staticmethod\n    def _resolve_color_list(\n        colors: Color | list[Color],\n        points_count: int,\n    ) -> list[Color]:\n        \"\"\"Return a per-keypoint color list for a single instance.\"\"\"\n        if isinstance(colors, list):","sourceCodeStart":951,"sourceCodeEnd":987,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/key_points/annotators.py#L951-L987","documentation":"Raised by verify_clean_wheel.py's _validate_manifest when the set of non-comment, non-empty lines in the fallback smoke-manifest file does not exactly equal the script's hardcoded _MANIFEST_CHECKS set ({'draw-box', 'draw-rectangle', 'required-pyav', ...}). The manifest lists the smoke checks run against the installed wheel; the script requires the file and the expected contract to stay in lockstep so the fallback verification cannot silently lose coverage.","triggerScenarios":"Adding, renaming, or deleting a check in the manifest file without updating _MANIFEST_CHECKS in verify_clean_wheel.py (or vice versa); trailing whitespace or a stray non-comment line in the manifest being picked up as a check; editing one side on a branch and forgetting the other.","commonSituations":"Contributors extending the wheel smoke tests; a manifest path change; line-ending or encoding edits introducing phantom entries; rebase/merge where only one side of the paired constant/file was taken.","solutions":["Read the error message: it prints both the found set and the expected set — diff them to see the exact added/missing entry.","If you intentionally changed the manifest, update _MANIFEST_CHECKS in .github/scripts/verify_clean_wheel.py to match (or reverse the change).","Check for accidental lines: comments must start with '#'; blank lines are ignored but anything else counts as a check name.","Re-run the script to confirm the sets now match exactly."],"exampleFix":"# before: manifest adds a new check but script constant is stale\n# manifest file:  draw-box\\ndraw-rectangle\\nrequired-pyav\\ndraw-label   <- new line\n\n# after: update the paired constant in verify_clean_wheel.py\n_MANIFEST_CHECKS = {\n    \"draw-box\",\n    \"draw-rectangle\",\n    \"required-pyav\",\n    \"draw-label\",\n}","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef manifest_matches_expected(manifest: Path, expected: set[str]) -> bool:\n    \"\"\"Mirror of the script's check: non-comment, non-blank lines vs expected set.\"\"\"\n    checks = {\n        s for line in manifest.read_text(encoding='utf-8').splitlines()\n        if (s := line.strip()) and not s.startswith('#')\n    }\n    return checks == expected","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat the manifest file and _MANIFEST_CHECKS as a paired contract: change both in the same commit.","Diff the 'found' vs 'expected' sets printed in the error message — the symmetric difference pinpoints the drift.","Keep manifest lines bare check names only; any non-comment text becomes a check entry."],"tags":["ci","packaging","manifest","drift","valueerror"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}