roboflow/supervision · error · ValueError

Expected mapping in data.yaml at '{file_path}', got {type(da

Error message

Expected mapping in data.yaml at '{file_path}', got {type(data).__name__}.

What it means

Raised when the parsed YAML root of data.yaml is not a mapping (dict). The loader does data.get('names'), so the root must be a key/value mapping; a YAML file whose top level is a list, a scalar, or null cannot contain a names entry, and the error reports the offending root type.

Source

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

    all int-like (plain ints or digit strings) are sorted numerically so
    class index 10 follows index 9. All-non-numeric keys are sorted
    lexicographically. Mixed numeric/non-numeric keys raise ``ValueError``.
    Boolean YAML keys (``true``/``false``) are excluded from numeric sorting
    because ``bool`` is a subclass of ``int`` in Python.

    Args:
        file_path: Path to the data.yaml file.

    Returns:
        Class names in class-index order.

    Raises:
        ValueError: If the YAML root is not a mapping, if ``names`` is
            neither a list nor a dict, or if the dict has mixed key types.
    """
    data: dict[str, Any] = read_yaml_file(file_path=file_path)
    if not isinstance(data, dict):
        raise ValueError(
            f"Expected mapping in data.yaml at '{file_path}',"
            f" got {type(data).__name__}."
        )
    names = data.get("names")
    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

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Verify data_yaml_path points at the dataset's data.yaml, not names.txt or a labels file.
  2. Check the top of the file: entries like `path:`, `train:`, `names:` at column 0 indicate a mapping root.
  3. If the root is a list or scalar, restructure the file to a mapping with a names key.
  4. Quick sanity check: python -c "import yaml; print(type(yaml.safe_load(open('data.yaml'))))" should print dict.

Example fix

# before (root is a sequence)
- person
- car
# after (root is a mapping)
path: ./dataset
train: images/train
names:
  - person
  - car
Defensive patterns

Strategy: type-guard

Validate before calling

import yaml

def is_mapping_yaml(path: str) -> bool:
    """Check that a YAML file's root is a mapping (dict)."""
    with open(path) as f:
        return isinstance(yaml.safe_load(f), dict)

Type guard

def is_mapping(data: object) -> bool:
    """True when the parsed YAML root is a dict."""
    return isinstance(data, dict)

Try / catch

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

Prevention

When it happens

Trigger: DetectionDataset.from_yolo(data_yaml_path=...) where the yaml file's top-level structure is a sequence (leading '- ' items), a bare scalar, or empty/null — e.g. pointing data_yaml_path at a YOLO labels .txt (names file) instead of data.yaml, or at an empty file.

Common situations: Passing the old-style `names.txt` or a normalized .yaml misparsed as a list; truncated/empty data.yaml; wrong file passed via data_yaml_path; yaml produced by a tool that emits a top-level array.

Related errors


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