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
- Move the target directory to a filesystem with reliable RENAME_EXCHANGE (ext4/xfs/btrfs on kernel >= 3.15) — see also error 401.
- Serialize promotion so no two callers act on the same target set (lock file / mutex).
- Reproduce with a standalone probe that does RENAME_EXCHANGE then stat-checks both slots on the exact directory+FS.
- 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
- Probe every target's parent directory for reliable RENAME_EXCHANGE before apply.
- Never silently retry a parity failure — it usually means the FS lied about atomicity.
- Keep promotion off overlayfs/fuse/network filesystems.
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
- atomic overlay exchange is unavailable on this platform
- oracle stage root changed during verification
- oracle file changed during verification: {item.target}
- frozen overlay bytes do not match the authorized input
- repository root changed during overlay {phase}: {root}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/f61bcdc637785038.
Report an issue: GitHub.