roboflow/supervision · error · ValueError

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

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.

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.

Appendix: 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)