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

  1. Inspect the wheel's *.dist-info/METADATA Provides-Extra lines to find the offending extra name.
  2. Remove the opencv extra from pyproject.toml's [project.optional-dependencies]; document manual opencv installation in the README instead.
  3. 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.
  4. 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

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


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/74b89054ab3611d9. Report an issue: GitHub.