{"record":{"id":"52b4103e4143f41a","repo":"roboflow/supervision","slug":"all-data-dictionaries-must-have-the-same-keys-to-m","errorCode":null,"errorMessage":"All data dictionaries must have the same keys to merge.","messagePattern":"All data dictionaries must have the same keys to merge\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/detection/utils/internal.py","lineNumber":565,"sourceCode":"    Args:\n        data_list: The data payloads of the Detections instances. Each data payload\n            is a dictionary with the same keys, and the values are either lists or\n            npt.NDArray[np.generic].\n\n    Returns:\n        A single data payload containing the merged data, preserving the original data\n            types (list or npt.NDArray[np.generic]).\n\n    Raises:\n        ValueError: If data values within a single object have different lengths or if\n            dictionaries have different keys.\n    \"\"\"\n    if not data_list:\n        return {}\n\n    all_keys_sets = [set(data.keys()) for data in data_list]\n    if not all(keys_set == all_keys_sets[0] for keys_set in all_keys_sets):\n        raise ValueError(\"All data dictionaries must have the same keys to merge.\")\n\n    for data in data_list:\n        lengths = [len(value) for value in data.values()]\n        if len(set(lengths)) > 1:\n            raise ValueError(\n                \"All data values within a single object must have equal length.\"\n            )\n\n    merged_data: dict[str, Any] = {key: [] for key in all_keys_sets[0]}\n    for data in data_list:\n        for key in data:\n            merged_data[key].append(data[key])\n\n    for key in merged_data:\n        if all(isinstance(item, list) for item in merged_data[key]):\n            merged_data[key] = list(chain.from_iterable(merged_data[key]))\n        elif all(isinstance(item, np.ndarray) for item in merged_data[key]):\n            ndim = merged_data[key][0].ndim","sourceCodeStart":547,"sourceCodeEnd":583,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/detection/utils/internal.py#L547-L583","documentation":"The internal data-merge helper (used when concatenating/merging Detections objects) requires every Detections' data dict to have exactly the same key set, because each key's values are stacked column-wise across the objects. Heterogeneous keys (one Detections carrying 'class_name' that another lacks) would leave holes in the aligned arrays, so it fails fast.","triggerScenarios":"sv.Detections.merge([d1, d2]) where d1 has data={CLASS_NAME_DATA_FIELD: ...} and d2 has data={}; or concatenate() where one branch added tracker/confidence metadata keys (e.g. from ByteTrack) and another branch was constructed raw.","commonSituations":"Mixing tracker-annotated Detections with freshly constructed ones; one code path enriching data with custom keys and another not; filtering/empty Detections losing keys then being merged back in.","solutions":["Normalize keys before merging: add the missing key to each Detections with a placeholder aligned array (e.g. np.array([''] * len(d))).","Drop the extra keys from the richer Detections so all share the minimal common set you need.","Ensure every construction path in your pipeline populates the same data keys (centralize in a helper)."],"exampleFix":"# before\n merged = sv.Detections.merge([d_with_names, d_without_names])\n\n# after\n key = sv.CLASS_NAME_DATA_FIELD\n if key not in d_without_names.data:\n     d_without_names.data[key] = np.array([\"\"] * len(d_without_names), dtype=object)\n merged = sv.Detections.merge([d_with_names, d_without_names])","handlingStrategy":"validation","validationCode":"all_keys = [set(d.data.keys()) for d in detections_list]\nif len({frozenset(k) for k in all_keys}) != 1:\n    raise ValueError(f\"Mismatched data keys before merge: {all_keys}\")\nmerged = sv.Detections.merge(detections_list)","typeGuard":"def have_same_data_keys(detections_list: list[sv.Detections]) -> bool:\n    key_sets = {frozenset(d.data.keys()) for d in detections_list}\n    return len(key_sets) <= 1","tryCatchPattern":"try:\n    merged = sv.Detections.merge(detections_list)\nexcept ValueError as e:\n    logger.warning(\"Merge blocked by data-key mismatch: %s\", e)\n    common = set.intersection(*[set(d.data) for d in detections_list])\n    for d in detections_list:\n        for k in list(d.data):\n            if k not in common:\n                del d.data[k]\n    merged = sv.Detections.merge(detections_list)","preventionTips":["Populate data keys uniformly via one helper used by every construction path.","When enriching Detections conditionally, add placeholder arrays for the key everywhere.","Validate key sets before merge/concentrate in batch pipelines."],"tags":["detections","merge","data-dict","key-mismatch"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}