roboflow/supervision · error · ValueError
labels is a dict but class_id is None; KeyPoints must have c
Error message
labels is a dict but class_id is None; KeyPoints must have class_id set.
What it means
Raised by verify_clean_wheel.py when a wheel's METADATA declares a Provides-Extra whose name contains 'opencv' (case-insensitive). Beyond dropping the runtime requirement, the packaging policy also forbids shipping an opencv-named extra at all — users should install opencv themselves. This check runs right after the Requires-Dist check on the same metadata.
Source
Thrown at src/supervision/key_points/annotators.py:964
center_y - text_h // 2,
center_x + text_w // 2,
center_y + text_h // 2,
)
@staticmethod
def _resolve_labels(
labels: list[str] | dict[int, list[str]] | None,
points_count: int,
class_id: int | None = None,
) -> list[str]:
"""Return the label list for a single instance."""
if labels is None:
return [str(j) for j in range(points_count)]
resolved: list[str]
if isinstance(labels, dict):
if class_id is None:
raise ValueError(
"labels is a dict but class_id is None; "
"KeyPoints must have class_id set."
)
if class_id not in labels:
raise ValueError(f"No labels defined for class_id={class_id}.")
resolved = labels[class_id]
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(View on GitHub (pinned to 7f254d9784)
Solutions
- Inspect the wheel's *.dist-info/METADATA Provides-Extra lines to find the offending extra name.
- Remove the opencv extra from pyproject.toml's [project.optional-dependencies]; document manual opencv installation in the README instead.
- If a variant install is genuinely needed, work with the maintainers to update the verification policy and packaging docs together rather than bypassing the check.
- Rebuild and re-run .github/scripts/verify_clean_wheel.py to confirm a clean pass.
Example fix
# before (pyproject.toml) [project.optional-dependencies] opencv = ["opencv-python-headless"] # after [project.optional-dependencies] # (no opencv extra; users install opencv separately) dev = ["pytest", "ruff"]
Defensive patterns
Strategy: validation
Validate before calling
def wheel_has_no_opencv_extra(wheel: pathlib.Path) -> bool:
"""True if no Provides-Extra line mentions opencv."""
with zipfile.ZipFile(wheel) as z:
meta = next(n for n in z.namelist() if n.endswith('/METADATA'))
text = z.read(meta).decode()
return not any(
line.startswith('Provides-Extra:') and 'opencv' in line.lower()
for line in text.splitlines()
) Prevention
- Do not add opencv-named extras to packaging metadata; document manual opencv installation instead.
- Grep pyproject.toml for 'opencv' in optional-dependencies before opening a PR that touches packaging.
- Keep packaging policy and the verify_clean_wheel checks in the same PR so they never drift apart.
When it happens
Trigger: Declaring [project.optional-dependencies] opencv = [...] in pyproject.toml so the wheel advertises Provides-Extra: opencv; renaming an extra to something containing 'opencv' (e.g. 'opencv-headless'); building the wheel before removing the extra from packaging config.
Common situations: Contributors trying to make opencv installation convenient via an extra after the runtime dependency was removed; fork maintainers re-adding an opencv extra without updating the verification script's expectations; release CI failing on a branch that altered optional-dependency groups.
Related errors
- Number of labels ({len(resolved)}) must match number of key
- Number of colors ({len(colors)}) must match number of key po
- No labels defined for class_id={class_id}.
- All sigma values must be positive
- color length ({len(color_seq)}) must match sigma length ({le
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/74b89054ab3611d9.
Report an issue: GitHub.