abhigyanpatwari/GitNexus · error · ValueError
{label} changed while being read: {path}
Error message
{label} changed while being read: {path} What it means
Thrown by _bounded_regular_bytes at the open-time identity check (the only raise with this exact message, evolution.py:102). After lstat (line 90) and os.open with O_NOFOLLOW (line 98), an fstat is compared against the pre-open metadata: the descriptor must still be a regular file with identical st_dev/st_ino. If not, the file was replaced, renamed, or turned into a non-regular file in the window between stat and open — a TOCTOU condition the harness refuses to silently absorb.
Source
Thrown at eval/workflow_bench/evolution.py:126
break
chunks.append(chunk)
remaining -= len(chunk)
content = b"".join(chunks)
if len(content) > limit:
raise ValueError(f"{label} exceeds the bounded evidence limit")
after = os.fstat(descriptor)
if (
opened.st_dev,
opened.st_ino,
opened.st_size,
opened.st_mtime_ns,
) != (
after.st_dev,
after.st_ino,
after.st_size,
after.st_mtime_ns,
) or len(content) != opened.st_size:
raise ValueError(f"{label} changed while being read: {path}")
return content
finally:
os.close(descriptor)
def candidate_overlay_payload(overlay: Path) -> tuple[str, list[tuple[PurePosixPath, bytes]]]:
"""Return the sole validated, bounded candidate payload and its digest."""
root = overlay.expanduser().absolute()
payload: list[tuple[PurePosixPath, bytes]] = []
remaining = MAX_CANDIDATE_OVERLAY_BYTES
for source in candidate_overlay_files(root):
relative = PurePosixPath(source.relative_to(root).as_posix())
_require_directory_chain(
root,
Path(*relative.parent.parts),
label="candidate overlay directory",
)View on GitHub (pinned to d540b00184)
Solutions
- Copy the overlay to a private, read-only directory and pass that copy to the harness so no other writer can race it.
- Stop all concurrent editors/formatters/IDEs touching the overlay during the run.
- If transient (filesystem jitter), snapshot the overlay with shutil.copytree into a tempfile.mkdtemp and retry.
- Make the overlay tree read-only (chmod -R a-w) before invoking the harness.
Example fix
# before: pass a live overlay dir an editor may touch
apply_candidate_overlay(Path('overlay'), worktree, sandbox=sandbox)
# after: snapshot to a private dir first
import tempfile, shutil
snap = Path(tempfile.mkdtemp(prefix='wfbench-overlay-snap-'))
shutil.copytree('overlay', snap, dirs_exist_ok=False)
for p in snap.rglob('*'): p.chmod(0o500)
apply_candidate_overlay(snap, worktree, sandbox=sandbox) Defensive patterns
Strategy: validation
Validate before calling
import os, stat, shutil, tempfile
from pathlib import Path
def freeze_overlay(src: Path) -> Path:
"""Copy overlay to a private real dir and make it read-only to defeat TOCTOU."""
snap = Path(tempfile.mkdtemp(prefix='wfbench-snap-'))
shutil.copytree(src, snap / 'overlay')
for p in (snap / 'overlay').rglob('*'):
p.chmod(0o500 if p.is_dir() else 0o400)
return snap / 'overlay' Type guard
null
Try / catch
try:
apply_candidate_overlay(overlay, worktree, sandbox=sandbox)
except ValueError as exc:
if 'changed while opening' in str(exc):
overlay = freeze_overlay(original_overlay) # then retry once
apply_candidate_overlay(overlay, worktree, sandbox=sandbox) Prevention
- Never point the harness at an overlay an editor/formatter may rewrite.
- Snapshot the overlay into a private read-only directory before each run.
- On shared/cloud filesystems, copy the overlay to local disk first.
When it happens
Trigger: Another process replaces/rename the overlay file between the lstat and the O_NOFOLLOW open; an editor or formatter rewrites the file mid-run; a symlink swap attack against the overlay path; the file is deleted and recreated concurrently.
Common situations: Running the benchmark while an IDE/formatter/git checkout rewrites the overlay; pointing the overlay at a directory under active sync (Dropbox/network FS); a CI step that regenerates the overlay concurrently with evaluation.
Related errors
- overlay destination changed while being read: {target}
- Analyzer build changed while its identity was being computed
- Analyzer dependency runtime changed while its identity was b
- Analyzer build or dependency runtime changed while its ident
- {label} changed while opening: {path}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/e63501d83ff77464.
Report an issue: GitHub.