abhigyanpatwari/GitNexus · error · ValueError
overlay destination drifted before apply: {replacement['targ
Error message
overlay destination drifted before apply: {replacement['target']} What it means
Thrown in the pre-publication loop of `apply_promoted_overlay` when, after staging candidate and backup files but before any exchange, a target's current on-disk state no longer equals its `base_state` captured during preparation. This detects concurrent edits that landed in the window between prepare and publish.
Source
Thrown at eval/workflow_bench/promotion_apply.py:738
replacement["backup"] = _stage_replacement_at(
item["parent_descriptor"],
item["original"],
item["mode"],
)
except _StagingCleanupError as stage_exc:
replacement["backup"] = stage_exc.name
raise
# Recheck the entire compare set after staging and before the first
# replacement, then check each member immediately before its swap.
_validate_prepared_paths(
repo_root,
root_descriptor,
replacements,
phase="pre-publication",
)
for replacement in replacements:
if current_state(replacement) != replacement["base_state"]:
raise ValueError(f"overlay destination drifted before apply: {replacement['target']}")
for replacement in replacements:
_validate_prepared_paths(
repo_root,
root_descriptor,
[replacement],
phase="publication",
)
if current_state(replacement) != replacement["base_state"]:
raise ValueError(f"overlay destination drifted during apply: {replacement['target']}")
previous_identity = _entry_identity_at(
replacement["parent_descriptor"],
replacement["name"],
)
replacement["publication_previous_identity"] = previous_identity
try:
_exchange_at(
replacement["parent_descriptor"],
replacement["candidate"],View on GitHub (pinned to d540b00184)
Solutions
- Re-capture `expected_target_bases` and `expected_digest`, then retry the apply — the new capture will include the concurrent edit.
- Serialize promotion: ensure no other writer (formatter, IDE, build) runs against the repo during apply.
- Take a working-tree lock (e.g. `.git/index.lock` convention or a harness-level mutex) around capture+apply.
- If a specific tool is the culprit (ruff/black/prettier), disable it for the repo or run promotion in a clean checkout.
Example fix
# before: apply raced with an editor autosave
apply_promoted_overlay(overlay, expected_target_bases=bases) # -> ValueError drifted
# after: serialize promotion and re-capture after any concurrent edit
import fcntl
with open(repo_root / '.wfbench-promote.lock', 'w') as lock:
fcntl.flock(lock, fcntl.LOCK_EX)
bases = destination_base_digests(overlay)
apply_promoted_overlay(overlay, expected_target_bases=bases) Defensive patterns
Strategy: validation
Validate before calling
import fcntl, contextlib
from workflow_bench.promotion_apply import destination_base_digests
@contextlib.contextmanager
def promote_lock(repo_root):
with open(repo_root / ".wfbench-promote.lock", "w") as f:
fcntl.flock(f, fcntl.LOCK_EX)
yield
# hold the lock across capture+apply so no writer can drift a target
with promote_lock(repo_root):
bases = destination_base_digests(overlay)
apply_promoted_overlay(overlay, expected_target_bases=bases) Type guard
null
Try / catch
try:
apply_promoted_overlay(overlay, expected_target_bases=bases)
except ValueError as exc:
if "drifted before apply" in str(exc):
# a concurrent writer landed: re-capture and retry under a lock
with promote_lock(repo_root):
bases = destination_base_digests(overlay)
apply_promoted_overlay(overlay, expected_target_bases=bases)
raise Prevention
- Serialize promotion with a file lock so no editor/formatter can interleave.
- Run promotion in a clean checkout that no IDE touches.
- Disable autosave/format-on-save for the repo during CI.
When it happens
Trigger: A concurrent process (IDE formatter, build tool, another git operation, an editor autosave) modified one of the destination files between `_prepare_targets` and the `current_state(replacement) != base_state` check at promotion_apply.py:737. The promote operation aborts before doing any exchange.
Common situations: An IDE autosaves a file mid-promotion; a `pre-commit` hook or formatter runs in parallel; a developer edits a target while CI is promoting; background indexing rewrites a file; another `apply_promoted_overlay` call raced on the same repo.
Related errors
- overlay destination drifted during apply: {replacement['targ
- overlay destination base binding mismatch:
- post-apply parity check failed: {replacement['target']}
- Analyzer build or dependency runtime changed during analysis
- {label} changed while being read: {path}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/dc5fa8a9a35e1e3c.
Report an issue: GitHub.