roboflow/supervision · error · ValueError

Expected 'names' to be a list or dict in data.yaml at '{file

Error message

Expected 'names' to be a list or dict in data.yaml at '{file_path}', got {type(names).__name__}.

What it means

Raised by the YOLO data.yaml class-name loader when the 'names' entry is neither a list nor a dict (e.g. a plain string or a number). Ultralytics-style data.yaml must define names either as a list in class-index order or as a mapping of index/name; anything else cannot be mapped to ordered class names, so supervision raises with the actual type found.

Source

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

            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:
    base_name, _ = os.path.splitext(image_name)
    return base_name + ".txt"


def yolo_annotations_to_detections(
    lines: list[str],
    resolution_wh: tuple[int, int],
    with_masks: bool,
    is_obb: bool = False,
) -> Detections:
    if len(lines) == 0:
        return Detections.empty()

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Open the data.yaml at the path in the error and inspect the `names:` entry.
  2. Rewrite names as a list (order = class index): names: [person, car, dog]
  3. Or as an explicit index map: names: {0: person, 1: car, 2: dog}.
  4. Re-run DetectionDataset.from_yolo; if it still fails, validate the yaml loads as expected with PyYAML first.

Example fix

# before (data.yaml)
names: person
# after (data.yaml)
names:
  - person
  - car
Defensive patterns

Strategy: type-guard

Validate before calling

import yaml

def load_names(data_yaml: str) -> list[str]:
    """Validate the names entry of a YOLO data.yaml before use."""
    names = yaml.safe_load(open(data_yaml)).get('names')
    assert isinstance(names, (list, dict)), type(names)
    return list(names) if isinstance(names, list) else [names[k] for k in sorted(names)]

Type guard

def is_valid_names(names: object) -> bool:
    """names must be a list or a dict to be usable as class names."""
    return isinstance(names, (list, dict))

Try / catch

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

Prevention

When it happens

Trigger: DetectionDataset.from_yolo(data_yaml_path=...) where the YAML contains e.g. `names: person` (single bare string), `names: 80`, `names: null`, or a nested structure instead of a list/dict.

Common situations: Typo in data.yaml (missing `-` bullet or braces); minimal hand-written yaml that gives a scalar class name; a YAML indentation mistake that turns a list into a string; using a non-Ultralytics yaml schema.

Related errors


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