abhigyanpatwari/GitNexus · error · ValueError

duplicate overlay destination: {target}

Error message

duplicate overlay destination: {target}

What it means

Thrown in `_prepare_targets` when two entries in the overlay payload map to the same canonical/shipped target path. `mirror_targets(relative)` is expanded for every `(relative, content)` pair and the set `seen` rejects the second occurrence, so the overlay's own content produces an ambiguous destination.

Source

Thrown at eval/workflow_bench/promotion_apply.py:451

    if error in {errno.ENOSYS, errno.EINVAL, errno.EOPNOTSUPP}:
        raise RuntimeError("atomic overlay exchange is unavailable on this filesystem")
    raise OSError(error, os.strerror(error), f"{left} <-> {right}")


def _prepare_targets(
    payload: list[tuple[PurePosixPath, bytes]],
    repo_root: Path,
) -> tuple[Path, int, list[dict[str, Any]]]:
    """Resolve and snapshot every canonical/shipped destination exactly once."""

    root, root_descriptor = _open_repository_root(repo_root)
    prepared: list[dict[str, Any]] = []
    seen: set[PurePosixPath] = set()
    try:
        for relative, content in payload:
            for target in mirror_targets(relative):
                if target in seen:
                    raise ValueError(f"duplicate overlay destination: {target}")
                seen.add(target)
                parent_descriptor = _open_target_parent(root_descriptor, target)
                try:
                    original, mode = _read_destination_at(
                        parent_descriptor,
                        target.name,
                        target=target,
                    )
                except BaseException:
                    os.close(parent_descriptor)
                    raise
                prepared.append(
                    {
                        "target": target,
                        "destination": root / target,
                        "parent_path": root / target.parent,
                        "parent_descriptor": parent_descriptor,
                        "name": target.name,

View on GitHub (pinned to d540b00184)

Solutions

  1. Inspect the offending target printed in the message and search the overlay payload for entries whose `mirror_targets()` yields it.
  2. Run `candidate_overlay_payload(overlay)` and print `[t for rel, _ in payload for t in mirror_targets(rel)]` to find duplicates before calling apply.
  3. Remove the duplicate entry from the overlay, or fix the `mirror_targets` mapping that creates the collision.
  4. Add a unit test that asserts the deduplicated target set equals the raw target list.

Example fix

# diagnostic
from workflow_bench.promotion_apply import candidate_overlay_payload, mirror_targets
from collections import Counter
_, payload = candidate_overlay_payload(overlay)
targets = [str(t) for rel, _ in payload for t in mirror_targets(rel)]
print([t for t, c in Counter(targets).items() if c > 1])  # remove these from the overlay
Defensive patterns

Strategy: validation

Validate before calling

from collections import Counter
from pathlib import PurePosixPath
from workflow_bench.promotion_apply import candidate_overlay_payload, mirror_targets

def overlay_targets_are_unique(overlay) -> bool:
    _, payload = candidate_overlay_payload(overlay)
    targets = [str(t) for rel, _ in payload for t in mirror_targets(rel)]
    dupes = [t for t, c in Counter(targets).items() if c > 1]
    if dupes:
        print("duplicate targets:", dupes)
        return False
    return True

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: The overlay file declares two canonical paths whose `mirror_targets()` expansion collides (e.g. the same path shipped twice, or a path and its mirror alias resolving to the same target). Reproducible by calling `apply_promoted_overlay()` or `destination_base_digests()` with such an overlay.

Common situations: Editing an overlay manifest to add a path without removing its old alias; a `mirror_targets` rule that maps both a path and a sibling to the same target; renaming a file but leaving the old entry; merging two overlays whose targets overlap.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/8ec2a6bba7e4611c. Report an issue: GitHub.