roboflow/supervision · error · ValueError
Number of colors ({len(colors)}) must match number of key po
Error message
Number of colors ({len(colors)}) must match number of key points ({points_count}). What it means
Raised by verify_clean_wheel.py's _wheel_metadata when opening a wheel archive does not yield exactly one path ending in '/METADATA'. A valid wheel contains precisely one *.dist-info/METADATA file; zero means the wheel is malformed or the file is misplaced/misnamed, and more than one means duplicate dist-info directories got packed in. The script refuses to guess which metadata to validate.
Source
Thrown at src/supervision/key_points/annotators.py:989
else:
resolved = labels
if len(resolved) != points_count:
raise ValueError(
f"Number of labels ({len(resolved)}) must match "
f"number of key points ({points_count})."
)
return resolved
@staticmethod
def _resolve_color_list(
colors: Color | list[Color],
points_count: int,
) -> list[Color]:
"""Return a per-keypoint color list for a single instance."""
if isinstance(colors, list):
if len(colors) != points_count:
raise ValueError(
f"Number of colors ({len(colors)}) must match "
f"number of key points ({points_count})."
)
return colors
return [colors] * points_count
View on GitHub (pinned to 7f254d9784)
Solutions
- Inspect the archive: unzip -l yourwheel.whl | grep METADATA and confirm there is exactly one <name>.dist-info/METADATA entry.
- If zero entries: rebuild the wheel with a standard backend (python -m build --wheel) from a clean checkout instead of custom zipping.
- If multiple entries: delete stale dist-info directories from the build dir and rebuild; never merge two wheels' contents.
- Verify you are passing an actual built wheel (fresh artifact), not a renamed zip or sdist, to verify_clean_wheel.py.
Example fix
# before: hand-zipped 'wheel' with misplaced metadata zip -r custom.whl mypackage/ METADATA # METADATA at archive root -> 0 matches # after: build a compliant wheel # python -m build --wheel # dist/supervision-*.whl now contains supervision-x.y.z.dist-info/METADATA
Defensive patterns
Strategy: validation
Validate before calling
import zipfile, pathlib
def is_clean_wheel(wheel: pathlib.Path) -> bool:
"""True if the archive has exactly one */METADATA entry (valid wheel layout)."""
if not wheel.name.endswith('.whl'):
return False
with zipfile.ZipFile(wheel) as z:
return len([n for n in z.namelist() if n.endswith('/METADATA')]) == 1 Prevention
- Always build wheels with a standard backend (python -m build --wheel); never hand-zip or merge archives.
- In CI, verify the artifact is a fresh wheel from this build (name includes version and tag) before running verification.
- Run unzip -l on the wheel when this fails to see whether METADATA is missing, misplaced, or duplicated.
When it happens
Trigger: Passing a path that is not a real wheel (a zip renamed .whl, or an sdist); a custom build step that writes METADATA at a non-standard path (no '<pkg>.dist-info/' prefix, so endswith('/METADATA') misses it); a packaging bug or manual re-zip producing two dist-info directories; a corrupted download producing a truncated archive read as having no metadata.
Common situations: CI downloading wheels from an artifact store that mangles names or contents; developers hand-editing/re-zipping wheels to patch metadata; broken custom build backends (setuptools plugin, bazel rules) emitting non-compliant wheel layouts; pointing the verifier at the dist/ directory glob that matches a stale wheel plus a new one and reading the wrong file.
Related errors
- Number of labels ({len(resolved)}) must match number of key
- labels is a dict but class_id is None; KeyPoints must have c
- No labels defined for class_id={class_id}.
- module {__name__} has no attribute {name}
- Edge indices must use the 1-based convention and be within t
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/6f76c3a4c038e2b3.
Report an issue: GitHub.