abhigyanpatwari/GitNexus · critical · RuntimeError

atomic overlay exchange parity check failed: {replacement['t

Error message

atomic overlay exchange parity check failed: {replacement['target']}

What it means

Thrown immediately after a single `_exchange_at` returned success but the four-way parity check (destination==candidate_state, displaced==base_state, identity match on both slots) failed. The atomic swap reported success yet the resulting directory entries do not look like a clean RENAME_EXCHANGE, indicating kernel/filesystem misbehavior or a race that the syscall did not serialize.

Source

Thrown at eval/workflow_bench/promotion_apply.py:800

                completed.append(replacement)
            observed_destination = current_state(replacement)
            observed_previous = entry_state(replacement, replacement["candidate"])
            destination_identity = _entry_identity_at(
                replacement["parent_descriptor"],
                replacement["name"],
            )
            displaced_identity = _entry_identity_at(
                replacement["parent_descriptor"],
                replacement["candidate"],
            )
            if (
                observed_destination == replacement["candidate_state"]
                and observed_previous == replacement["base_state"]
                and destination_identity == replacement["candidate_identity"]
                and displaced_identity == previous_identity
            ):
                continue
            raise RuntimeError(f"atomic overlay exchange parity check failed: {replacement['target']}")
        for replacement in replacements:
            if (
                current_state(replacement) != replacement["candidate_state"]
                or entry_state(replacement, replacement["candidate"]) != replacement["base_state"]
                or _entry_identity_at(replacement["parent_descriptor"], replacement["name"])
                != replacement["candidate_identity"]
                or _entry_identity_at(replacement["parent_descriptor"], replacement["candidate"])
                != replacement["publication_previous_identity"]
            ):
                raise RuntimeError(f"post-apply parity check failed: {replacement['target']}")
        _validate_prepared_paths(
            repo_root,
            root_descriptor,
            replacements,
            phase="post-apply validation",
        )
        published_all = True
    except BaseException as exc:

View on GitHub (pinned to d540b00184)

Solutions

  1. Move the target directory to a filesystem with reliable RENAME_EXCHANGE (ext4/xfs/btrfs on kernel >= 3.15) — see also error 401.
  2. Serialize promotion so no two callers act on the same target set (lock file / mutex).
  3. Reproduce with a standalone probe that does RENAME_EXCHANGE then stat-checks both slots on the exact directory+FS.
  4. If reproducible, file a kernel/filesystem bug; meanwhile fall back to a non-atomic publish on a known-good FS.

Example fix

# probe RENAME_EXCHANGE reliability on the exact target FS before relying on it
import ctypes, os, tempfile
d = tempfile.mkdtemp(dir=str(repo_root))  # same FS as the targets
a = os.path.join(d, 'a'); b = os.path.join(d, 'b')
open(a,'w').write('A'); open(b,'w').write('B')
fd = os.open(d, os.O_RDONLY)
libc = ctypes.CDLL(None, use_errno=True)
libc.renameat2(fd, b'a', fd, b'b', 2)  # check return + both file contents after
Defensive patterns

Strategy: validation

Validate before calling

# see error 401's filesystem_supports_rename_exchange probe — run it on the
# EXACT parent directory of every target before relying on RENAME_EXCHANGE.
from workflow_bench.promotion_apply import _prepare_targets, candidate_overlay_payload

def all_target_parents_support_exchange(overlay, repo_root) -> bool:
    _, payload = candidate_overlay_payload(overlay)
    _, _, prepared = _prepare_targets(payload, repo_root)
    try:
        return all(filesystem_supports_rename_exchange(str(p["parent_path"])) for p in prepared)
    finally:
        from workflow_bench.promotion_apply import _close_prepared
        _close_prepared(prepared[0]["parent_descriptor"], prepared)  # close descriptors

Type guard

null

Try / catch

try:
    apply_promoted_overlay(overlay, expected_target_bases=bases)
except RuntimeError as exc:
    if "parity check failed" in str(exc):
        # suspect FS misbehaviour; do NOT auto-retry on the same FS
        raise SystemExit(f"parity failure on {exc}; move repo to ext4/xfs/btrfs")
    raise

Prevention

When it happens

Trigger: `renameat2(RENAME_EXCHANGE)` returned 0 but the destination slot does not hold the candidate bytes/identity or the displaced slot does not hold the original. Seen on filesystems that silently degrade RENAME_EXCHANGE, under heavy concurrent I/O, or when an external editor rewrote both slots in the same window.

Common situations: Overlayfs/fuse/NFS pretending to support RENAME_EXCHANGE; a kernel bug; an antivirus or sync client rewriting files mid-swap; concurrent `apply_promoted_overlay` on the same target; storage with non-atomic metadata updates.

Related errors


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