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
- Verify data_yaml_path points at the dataset's data.yaml, not names.txt or a labels file.
- Check the top of the file: entries like `path:`, `train:`, `names:` at column 0 indicate a mapping root.
- If the root is a list or scalar, restructure the file to a mapping with a names key.
- 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
- Point data_yaml_path at the dataset's data.yaml, never names.txt or label files.
- Top-level keys of data.yaml should be path/train/val/names — no leading dashes.
- Sanity-check with yaml.safe_load before loading large datasets.
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
- Expected 'names' to be a list or dict in data.yaml at '{file
- Expected 'names' dict in data.yaml at '{file_path}' to have
- Detections must have class_id attribute.
- Detections class_id must be a subset of source_to_target_map
- Class {class_name} not found in target classes. source_class
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/6b75debfab8b0208.
Report an issue: GitHub.