roboflow/supervision · error · ValueError

All metadata dictionaries must have the same keys to merge.

Error message

All metadata dictionaries must have the same keys to merge.

What it means

Raised by merge_metadata when concatenating Detections objects whose metadata dictionaries do not carry exactly the same set of keys. Metadata (e.g. video_id, source_path) must be homogeneous across all Detections being merged, because the merge cannot decide what value to use for a key that is missing in some inputs.

Source

Thrown at src/supervision/detection/utils/internal.py:624

    Warning: Assumes that empty detections were filtered-out before passing metadata to
    this function.

    Args:
        metadata_list: A list of metadata dictionaries to merge.

    Returns:
        A single merged metadata dictionary.

    Raises:
        ValueError: If there are conflicting values for the same key or if
        dictionaries have different keys.
    """
    if not metadata_list:
        return {}

    all_keys_sets = [set(metadata.keys()) for metadata in metadata_list]
    if not all(keys_set == all_keys_sets[0] for keys_set in all_keys_sets):
        raise ValueError("All metadata dictionaries must have the same keys to merge.")

    merged_metadata: _MetadataType = {}
    for metadata in metadata_list:
        for key, value in metadata.items():
            if key not in merged_metadata:
                merged_metadata[key] = value
                continue

            other_value = merged_metadata[key]
            if isinstance(value, np.ndarray) and isinstance(other_value, np.ndarray):
                if not np.array_equal(merged_metadata[key], value):
                    raise ValueError(
                        f"Conflicting metadata for key: '{key}': "
                        f"{type(value)}, {type(other_value)}."
                    )
            elif isinstance(value, np.ndarray) or isinstance(other_value, np.ndarray):
                # Since [] == np.array([]).
                raise ValueError(

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Make every Detections carry the identical metadata keys, filling missing ones with a default (e.g. metadata={'video_id': d.metadata.get('video_id', -1)}) before merging
  2. If the keys are intentionally different, strip metadata (rebuild Detections with metadata={}) before concatenating
  3. Union the keys explicitly per input and fill defaults in your own pre-merge step so the library invariant (all_keys_sets equal) holds

Example fix

// before
merged = sv.Detections.merge([d1, d2])  # d1.metadata={'video_id':0}, d2.metadata={}
// after
keys = d1.metadata.keys() | d2.metadata.keys()
d1.metadata = {k: d1.metadata.get(k, None) for k in keys}
d2.metadata = {k: d2.metadata.get(k, None) for k in keys}
merged = sv.Detections.merge([d1, d2])
Defensive patterns

Strategy: validation

Validate before calling

def assert_mergeable_metadata(detections_list):
    key_sets = [set(d.metadata.keys()) for d in detections_list]
    first = key_sets[0]
    for d, ks in zip(detections_list, key_sets):
        assert ks == first, f"metadata keys differ: {ks} vs {first} (obj {d})"

Try / catch

try:
    merged = sv.Detections.merge(detections_list)
except ValueError as e:
    if "same keys to merge" in str(e):
        keys = set().union(*(d.metadata.keys() for d in detections_list))
        for d in detections_list:
            d.metadata = {k: d.metadata.get(k, None) for k in keys}
        merged = sv.Detections.merge(detections_list)
    else:
        raise

Prevention

When it happens

Trigger: Detections.merge([...]) or Detections.concatenate([...]) (core.py:2495), Detections.__add__ path, merge of two single-detection Detections (core.py:3462), or annotations.merge() (core.py:3366) where one Detections was built with metadata={'video_id': 1} and another with metadata={} or a differently-keyed dict.

Common situations: Concatenating per-frame Detections in a loop where some frames got metadata and others did not; merging detections from two different models/pipelines that attach different metadata keys; incrementally adding a new metadata key to an existing pipeline while old pickled/cached Detections lack it.

Related errors


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