roboflow/supervision · error · ValueError

Expected 'names' dict in data.yaml at '{file_path}' to have

Error message

Expected 'names' dict in data.yaml at '{file_path}' to have either all numeric or all non-numeric keys, got a mix: numeric {mixed_numeric} and non-numeric {mixed_other} keys.

What it means

Raised when data.yaml defines 'names' as a dict whose keys mix integer-like keys (0, 1, '2') with non-integer keys ('person', 'car'). A mixed mapping is ambiguous: it is unclear whether keys are class indices, so the loader refuses rather than guessing an ordering. Fully-numeric dicts are sorted numerically; fully non-numeric dicts are sorted lexically.

Source

Thrown at src/supervision/dataset/formats/yolo.py:122

    if isinstance(names, dict):
        keys = list(names.keys())

        def _is_int_like(key: Any) -> bool:
            # bool subclasses int; YAML `true`/`false` must not become class indices
            if isinstance(key, bool):
                return False
            if isinstance(key, int):
                return True
            if isinstance(key, str):
                stripped = key.strip()
                return stripped.isdigit()
            return False

        int_like = [_is_int_like(k) for k in keys]
        if any(int_like) and not all(int_like):
            mixed_numeric = [k for k, il in zip(keys, int_like) if il][:3]
            mixed_other = [k for k, il in zip(keys, int_like) if not il][:3]
            raise ValueError(
                f"Expected 'names' dict in data.yaml at '{file_path}' to have either "
                f"all numeric or all non-numeric keys, got a mix: "
                f"numeric {mixed_numeric} and non-numeric {mixed_other} keys."
            )
        if all(int_like):
            sorted_keys = sorted(keys, key=lambda k: int(k))
        else:
            sorted_keys = sorted(keys, key=str)
        return [str(names[key]) for key in sorted_keys]
    if isinstance(names, list):
        return [str(name) for name in names]
    raise ValueError(
        "Expected 'names' to be a list or dict in data.yaml at "
        f"'{file_path}', got {type(names).__name__}."
    )


def _image_name_to_annotation_name(image_name: str) -> str:

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Inspect the names mapping in the data.yaml path from the error; the message lists up to 3 offending keys of each kind.
  2. Make all keys integer class indices: names: {0: person, 1: dog}.
  3. Or make all keys class names if using a name-keyed map — but index-keyed is the convention Ultralytics uses.
  4. Prefer the list form names: [person, dog] to remove key-typing ambiguity entirely.

Example fix

# before (data.yaml)
names:
  0: person
  dog: 1
# after (data.yaml)
names:
  0: person
  1: dog
Defensive patterns

Strategy: validation

Validate before calling

def uniform_name_keys(names: dict) -> bool:
    """Check a names dict has all-numeric or all-non-numeric keys."""
    def int_like(k):
        return isinstance(k, int) and not isinstance(k, bool) or (
            isinstance(k, str) and k.strip().isdigit())
    flags = [int_like(k) for k in names]
    return all(flags) or not any(flags)

Try / catch

try:
    dataset = sv.DetectionDataset.from_yolo(data_yaml_path='data.yaml')
except ValueError as e:
    if 'mixed' in str(e) and 'keys' in str(e):
        raise SystemExit(f'Normalize names keys in data.yaml: {e}') from e
    raise

Prevention

When it happens

Trigger: DetectionDataset.from_yolo(data_yaml_path=...) with names like {0: person, dog: 1} — some YAML files merge an index map with a name map or have typos such as quoting only some indices.

Common situations: Hand-merged yaml from two sources; a name key that looks like a class name but is a digit string typo; annotation tools that append names incrementally mixing conventions; yaml where keys auto-typed inconsistently (quoted vs unquoted).

Related errors


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