{"record":{"id":"0cd08cebf6dbde8b","repo":"abhigyanpatwari/GitNexus","slug":"post-apply-parity-check-failed-replacement-targ","errorCode":null,"errorMessage":"post-apply parity check failed: {replacement['target']}","messagePattern":"post-apply parity check failed: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"eval/workflow_bench/promotion_apply.py","lineNumber":810,"sourceCode":"            )\n            if (\n                observed_destination == replacement[\"candidate_state\"]\n                and observed_previous == replacement[\"base_state\"]\n                and destination_identity == replacement[\"candidate_identity\"]\n                and displaced_identity == previous_identity\n            ):\n                continue\n            raise RuntimeError(f\"atomic overlay exchange parity check failed: {replacement['target']}\")\n        for replacement in replacements:\n            if (\n                current_state(replacement) != replacement[\"candidate_state\"]\n                or entry_state(replacement, replacement[\"candidate\"]) != replacement[\"base_state\"]\n                or _entry_identity_at(replacement[\"parent_descriptor\"], replacement[\"name\"])\n                != replacement[\"candidate_identity\"]\n                or _entry_identity_at(replacement[\"parent_descriptor\"], replacement[\"candidate\"])\n                != replacement[\"publication_previous_identity\"]\n            ):\n                raise RuntimeError(f\"post-apply parity check failed: {replacement['target']}\")\n        _validate_prepared_paths(\n            repo_root,\n            root_descriptor,\n            replacements,\n            phase=\"post-apply validation\",\n        )\n        published_all = True\n    except BaseException as exc:\n        rollback_failures: list[str] = []\n        for replacement in reversed(completed):\n            try:\n                destination_identity = _entry_identity_at(\n                    replacement[\"parent_descriptor\"],\n                    replacement[\"name\"],\n                )\n                temporary_identity = _entry_identity_at(\n                    replacement[\"parent_descriptor\"],\n                    replacement[\"candidate\"],","sourceCodeStart":792,"sourceCodeEnd":828,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/promotion_apply.py#L792-L828","documentation":"Thrown in the post-apply loop after every individual exchange passed its own parity check. The full re-validation across all replacements found at least one whose destination/candidate slot identity or state drifted, meaning something changed the entries between their individual swaps and the final global check.","triggerScenarios":"All swaps succeeded individually, but a concurrent writer (or filesystem behavior) altered one or more slots before the global post-apply verification at promotion_apply.py:801-810. Triggers rollback of completed replacements.","commonSituations":"Concurrent editor/formatter touched a target after its swap but before the final loop; background indexer; an IDE 'restore' that overwrote a just-promoted file; same root causes as 409/410 but landing late.","solutions":["Serialize the entire apply (capture + publish + verify) under an exclusive lock so no writer can interleave.","Run promotion in a clean, isolated checkout that no IDE/build touches.","After a clean rollback (see error 414) re-capture evidence and retry.","Investigate the specific target named in the message for a process that writes it post-swap."],"exampleFix":"# before: post-apply global check found drift\napply_promoted_overlay(overlay, expected_target_bases=bases)  # -> RuntimeError\n# after: isolate + lock so no writer can land between swap and final check\nwith promote_lock(repo_root):  # see error 410 example\n    apply_promoted_overlay(\n        overlay,\n        expected_target_bases=destination_base_digests(overlay),\n    )","handlingStrategy":"validation","validationCode":"# post-apply drift means a writer landed during the apply — same lock as 409/410.\nimport fcntl, contextlib\n\n@contextlib.contextmanager\ndef promote_lock(repo_root):\n    with open(repo_root / \".wfbench-promote.lock\", \"w\") as f:\n        fcntl.flock(f, fcntl.LOCK_EX); yield\n\nwith promote_lock(repo_root):\n    apply_promoted_overlay(overlay, expected_target_bases=bases)","typeGuard":"null","tryCatchPattern":"try:\n    apply_promoted_overlay(overlay, expected_target_bases=bases)\nexcept RuntimeError as exc:\n    if \"post-apply parity check failed\" in str(exc):\n        # rollback should have run; verify tree then re-capture+retry under lock\n        import subprocess; subprocess.run([\"git\", \"-C\", str(repo_root), \"status\"], check=False)\n    raise","preventionTips":["Hold the lock across the entire apply including the post-apply verification loop.","Confirm `git status` is clean after a post-apply rollback before retrying.","Treat a post-apply parity failure as evidence of a concurrent writer — find and silence it."],"tags":["integrity","parity","concurrency","overlay","transaction"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}