roboflow/supervision · error · ValueError

Expected covariance shape {expected_shape}, got {covariances

Error message

Expected covariance shape {expected_shape}, got {covariances_array.shape}.

What it means

Raised by ColorPalette.by_idx when the palette's colors list is empty, before any indexing happens. A ColorPalette with zero colors cannot serve a lookup, so the method refuses rather than returning None or wrapping an empty list. Any by_idx call — including by_idx(0) — on an empty palette triggers this.

Source

Thrown at src/supervision/key_points/annotators.py:322

        sorted_indices = sorted(
            range(len(sigma_seq)), key=lambda i: sigma_seq[i], reverse=True
        )
        self.sigma = [sigma_seq[i] for i in sorted_indices]
        self.color = [color_seq[i] for i in sorted_indices]
        self.max_axis = max_axis

    def _get_covariances(self, key_points: KeyPoints) -> npt.NDArray[np.float32]:
        covariances = key_points.data.get("covariance")
        if covariances is None:
            raise ValueError(
                "key_points.data must contain 'covariance' with shape (N, K, 2, 2)."
            )
        covariances_array = cast(
            npt.NDArray[np.float32], np.asarray(covariances, dtype=np.float32)
        )
        expected_shape = (*key_points.xy.shape[:2], 2, 2)
        if covariances_array.shape != expected_shape:
            raise ValueError(
                f"Expected covariance shape {expected_shape}, "
                f"got {covariances_array.shape}."
            )
        return covariances_array

    def _decompose_covariance(
        self, covariance: npt.NDArray[np.float32]
    ) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]] | None:
        """Eigendecompose a 2x2 covariance, returning sorted (eigenvalues, vectors)."""
        if not np.isfinite(covariance).all():
            return None
        try:
            eigenvalues, eigenvectors = np.linalg.eigh(covariance.astype(np.float64))
        except np.linalg.LinAlgError:
            return None
        if not np.isfinite(eigenvalues).all() or np.any(eigenvalues <= 0):
            return None
        order = np.argsort(eigenvalues)[::-1]

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Ensure the colors list passed to sv.ColorPalette(...) or from_hex([...]) is non-empty.
  2. Default to the built-in palette when your dynamic list is empty: palette = sv.ColorPalette.from_hex(hexes) if hexes else sv.ColorPalette.DEFAULT.
  3. Add an early check in config-loading code that rejects or warns on empty color lists instead of constructing the palette.
  4. If you only need cyclic colors over unknown class counts, construct a palette of a fixed size once and rely on by_idx's modulo wrapping.

Example fix

# before
palette = sv.ColorPalette.from_hex([])  # later palette.by_idx(0) raises

# after
palette = sv.ColorPalette.from_hex(hexes) if hexes else sv.ColorPalette.DEFAULT
# or simply: palette = sv.ColorPalette.from_hex(hexes or ['#FF0000', '#00FF00', '#0000FF'])
Defensive patterns

Strategy: validation

Validate before calling

if not hex_colors:
    raise ValueError(f"color list is empty; cannot build palette: {hex_colors!r}")
palette = sv.ColorPalette.from_hex(hex_colors)

# or fall back to the default palette:
# palette = sv.ColorPalette.from_hex(hex_colors or ['#FF0000', '#00FF00', '#0000FF'])

Type guard

def has_colors(palette: sv.ColorPalette) -> bool:
    """True if the palette can serve by_idx lookups."""
    return len(palette.colors) > 0

Prevention

When it happens

Trigger: Constructing sv.ColorPalette(colors=[]) or sv.ColorPalette.from_hex([]) then calling .by_idx(i); building palettes from a dynamically generated hex list that is empty on the first iteration; deserializing a palette from config where the colors key is an empty list.

Common situations: Palette built from per-class colors loaded from user config that is missing/empty; loop-driven palette construction where the source list is empty for some class set; downstream of from_matplotlib with color_count < 1 being caught and defaulting to an empty palette instead.

Related errors


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