{"record":{"id":"d5e4c9e355bdd470","repo":"roboflow/supervision","slug":"number-of-labels-len-resolved-must-match-numb","errorCode":null,"errorMessage":"Number of labels ({len(resolved)}) must match number of key points ({points_count}).","messagePattern":"Number of labels \\((.+?)\\) must match number of key points \\((.+?)\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/key_points/annotators.py","lineNumber":975,"sourceCode":"        \"\"\"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):\n            if len(colors) != points_count:\n                raise ValueError(\n                    f\"Number of colors ({len(colors)}) must match \"\n                    f\"number of key points ({points_count}).\"\n                )\n            return colors","sourceCodeStart":957,"sourceCodeEnd":993,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/key_points/annotators.py#L957-L993","documentation":"Raised by the CI helper script .github/scripts/verify_clean_wheel.py when a built supervision wheel's METADATA still lists a Requires-Dist entry containing 'opencv' (case-insensitive). supervision has moved OpenCV to an optional dependency, so the wheel must not hard-require any opencv runtime; this check enforces that packaging invariant before publishing. It is a release-infrastructure assertion, not a runtime error library users normally see.","triggerScenarios":"Building the wheel while pyproject still declares opencv-python (or opencv-python-headless / opencv-contrib-python) in core dependencies; running verify_clean_wheel.py against a wheel built from a branch that re-added the runtime requirement; a build tool pulling in a stale lockfile that reinstates the requirement.","commonSituations":"Contributors adding opencv back to install_requires to fix a local import error; release workflows building from a dirty merge state; dependency-management tools (poetry/uv/pip-compile) regenerating metadata with the opencv requirement included.","solutions":["Open the wheel's *.dist-info/METADATA and confirm which Requires-Dist line contains 'opencv'.","Move the opencv dependency to an optional extra (e.g. [project.optional-dependencies]) or the appropriate dev/contrib group in pyproject.toml, matching supervision's packaging policy.","Rebuild the wheel from a clean checkout and re-run the verification script.","If the requirement comes from a generated lock/requirements file, regenerate it from pyproject.toml rather than hand-editing."],"exampleFix":"# before (pyproject.toml)\n[project]\ndependencies = [\"numpy\", \"opencv-python\", \"pyav\"]\n\n# after\n[project]\ndependencies = [\"numpy\", \"pyav\"]\n[project.optional-dependencies]\nopencv = [\"opencv-python-headless\"]","handlingStrategy":"validation","validationCode":"# In CI, before verify_clean_wheel.py:\nimport zipfile, pathlib\n\ndef wheel_has_no_opencv_requirement(wheel: pathlib.Path) -> bool:\n    with zipfile.ZipFile(wheel) as z:\n        meta = next(n for n in z.namelist() if n.endswith('/METADATA'))\n        text = z.read(meta).decode()\n    return not any(\n        line.startswith('Requires-Dist:') and 'opencv' in line.lower()\n        for line in text.splitlines()\n    )","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep opencv strictly out of [project].dependencies; it belongs only where project policy allows (and per this repo, not even as an extra).","Run the wheel verification script in CI before any publish step so packaging drift fails the build.","After any dependency-metadata change, build the wheel locally and inspect *.dist-info/METADATA Requires-Dist lines."],"tags":["ci","packaging","wheel","opencv","valueerror"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}