{"record":{"id":"356b545da90403a2","repo":"roboflow/supervision","slug":"expected-names-dict-in-data-yaml-at-file-path","errorCode":null,"errorMessage":"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.","messagePattern":"Expected 'names' dict in data\\.yaml at '(.+?)' to have either all numeric or all non-numeric keys, got a mix: numeric (.+?) and non-numeric (.+?) keys\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/dataset/formats/yolo.py","lineNumber":122,"sourceCode":"    if isinstance(names, dict):\n        keys = list(names.keys())\n\n        def _is_int_like(key: Any) -> bool:\n            # bool subclasses int; YAML `true`/`false` must not become class indices\n            if isinstance(key, bool):\n                return False\n            if isinstance(key, int):\n                return True\n            if isinstance(key, str):\n                stripped = key.strip()\n                return stripped.isdigit()\n            return False\n\n        int_like = [_is_int_like(k) for k in keys]\n        if any(int_like) and not all(int_like):\n            mixed_numeric = [k for k, il in zip(keys, int_like) if il][:3]\n            mixed_other = [k for k, il in zip(keys, int_like) if not il][:3]\n            raise ValueError(\n                f\"Expected 'names' dict in data.yaml at '{file_path}' to have either \"\n                f\"all numeric or all non-numeric keys, got a mix: \"\n                f\"numeric {mixed_numeric} and non-numeric {mixed_other} keys.\"\n            )\n        if all(int_like):\n            sorted_keys = sorted(keys, key=lambda k: int(k))\n        else:\n            sorted_keys = sorted(keys, key=str)\n        return [str(names[key]) for key in sorted_keys]\n    if isinstance(names, list):\n        return [str(name) for name in names]\n    raise ValueError(\n        \"Expected 'names' to be a list or dict in data.yaml at \"\n        f\"'{file_path}', got {type(names).__name__}.\"\n    )\n\n\ndef _image_name_to_annotation_name(image_name: str) -> str:","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/dataset/formats/yolo.py#L104-L140","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Inspect the names mapping in the data.yaml path from the error; the message lists up to 3 offending keys of each kind.","Make all keys integer class indices: names: {0: person, 1: dog}.","Or make all keys class names if using a name-keyed map — but index-keyed is the convention Ultralytics uses.","Prefer the list form names: [person, dog] to remove key-typing ambiguity entirely."],"exampleFix":"# before (data.yaml)\nnames:\n  0: person\n  dog: 1\n# after (data.yaml)\nnames:\n  0: person\n  1: dog","handlingStrategy":"validation","validationCode":"def uniform_name_keys(names: dict) -> bool:\n    \"\"\"Check a names dict has all-numeric or all-non-numeric keys.\"\"\"\n    def int_like(k):\n        return isinstance(k, int) and not isinstance(k, bool) or (\n            isinstance(k, str) and k.strip().isdigit())\n    flags = [int_like(k) for k in names]\n    return all(flags) or not any(flags)","typeGuard":null,"tryCatchPattern":"try:\n    dataset = sv.DetectionDataset.from_yolo(data_yaml_path='data.yaml')\nexcept ValueError as e:\n    if 'mixed' in str(e) and 'keys' in str(e):\n        raise SystemExit(f'Normalize names keys in data.yaml: {e}') from e\n    raise","preventionTips":["Use index keys consistently: names: {0: a, 1: b} — never mix with name keys.","Or use the plain list form to eliminate key typing.","Avoid hand-merging names maps from multiple yaml files."],"tags":["yolo","dataset","yaml","config"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}