abhigyanpatwari/GitNexus · error · RuntimeError
overlay apply failed and all replacements were rolled back
Error message
overlay apply failed and all replacements were rolled back
What it means
Thrown from the `except` block of `apply_promoted_overlay` when the apply failed but every completed replacement was rolled back cleanly (`rollback_failures` empty, `rollback_complete=True`). The working tree should be back to its pre-apply state; this is the 'safe' failure outcome — no recovery artifact is written.
Source
Thrown at eval/workflow_bench/promotion_apply.py:878
rollback_failures.append(f"{replacement['target']}: {type(rollback_exc).__name__}: {rollback_exc}")
else:
if not rollback_exchange_is_valid(replacement, temporary_identity, displaced_state):
rollback_failures.append(f"{replacement['target']}: rollback parity check failed")
if rollback_failures:
preserve_backups = True
recovery = _write_recovery_artifact(
root_descriptor,
repo_root,
failure=exc,
rollback_failures=rollback_failures,
replacements=replacements,
transaction_state="rollback-incomplete",
)
raise RuntimeError(f"overlay apply failed and rollback was incomplete; recovery: {recovery}") from exc
rollback_complete = True
if isinstance(exc, (KeyboardInterrupt, SystemExit)):
raise
raise RuntimeError("overlay apply failed and all replacements were rolled back") from exc
finally:
active_failure = sys.exc_info()[1]
try:
if not preserve_backups:
cleanup_failures: list[str] = []
cleanup_exception: BaseException | None = None
for replacement in replacements:
for temporary in (replacement["candidate"], replacement["backup"]):
if temporary is None:
continue
try:
_unlink_temporary(replacement["parent_descriptor"], temporary)
except BaseException as cleanup_exc:
cleanup_exception = cleanup_exc
cleanup_failures.append(
f"{replacement['target']}:{temporary}: {type(cleanup_exc).__name__}: {cleanup_exc}"
)
breakView on GitHub (pinned to d540b00184)
Solutions
- Inspect the chained `__cause__` exception to learn the original failure (drift, parity, staging).
- Confirm the tree is clean: `git status --porcelain` and compare `destination_base_digests(overlay)` to your prior capture.
- Re-capture `expected_target_bases`/`expected_digest` and retry the apply once the root cause (concurrent writer, etc.) is resolved.
- No recovery artifact cleanup is needed because rollback was complete.
Example fix
try:
apply_promoted_overlay(overlay, expected_target_bases=bases)
except RuntimeError as exc:
# rollback completed cleanly; inspect original cause
print('apply rolled back:', exc.__cause__)
# re-capture and retry after silencing the concurrent writer
bases = destination_base_digests(overlay)
apply_promoted_overlay(overlay, expected_target_bases=bases) Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
try:
apply_promoted_overlay(overlay, expected_target_bases=bases)
except RuntimeError as exc:
if "all replacements were rolled back" in str(exc):
# safe state — inspect the original cause, re-capture, retry
original = exc.__cause__
print("apply aborted cleanly; original cause:", original)
bases = destination_base_digests(overlay)
apply_promoted_overlay(overlay, expected_target_bases=bases)
else:
raise Prevention
- This is the safe failure outcome — check `git status` is clean before retrying.
- Inspect `exc.__cause__` to learn the original failure and fix it before retry.
- Re-capture `expected_target_bases`/`expected_digest` after a rollback; never reuse the stale values.
When it happens
Trigger: Any pre-publication or mid-apply failure (drift at 409/410, staging error, parity failure) where the rollback loop successfully re-swapped all completed targets and verified each displaced state. The exception is re-raised (preserving the original cause via `from exc`) so the caller knows the apply did not publish.
Common situations: Transient drift (409/410) that the rollback fully reversed; a staging error before any exchange completed; KeyboardInterrupt during apply that was caught and rolled back; a single-target parity failure (411) where every earlier swap rolled back.
Related errors
- overlay apply failed and rollback was incomplete; recovery:
- repository root changed during overlay {phase}: {root}
- overlay destination parent changed during {phase}: {item['ta
- overlay destination drifted during apply: {replacement['targ
- post-apply parity check failed: {replacement['target']}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/0e3f0d1d47c54d98.
Report an issue: GitHub.