abhigyanpatwari/GitNexus · error · OSError
short write while staging overlay replacement
Error message
short write while staging overlay replacement
What it means
All errors below are raised by internal helpers of `eval/workflow_bench/promotion_apply.py` and propagate to the caller of the public entry points: `apply_promoted_overlay(overlay, repo_root, *, expected_digest, expected_target_bases)`, `destination_base_digests(overlay, repo_root)`, `committed_destination_base_digests(overlay, repo_root, *, ref)` and `freeze_overlay(overlay, destination)`. The module applies promoted skill overlays across the canonical skill tree plus its shipped mirrors (`gitnexus/skills`, `gitnexus-claude-plugin/skills`) in a TOCTOU-hardened, symlink-rejecting, descriptor-bound transaction. In `_stage_replacement_at`, `os.write(descriptor, view)` returned a value <= 0 while a non-empty buffer remained. POSIX `write(2)` does not return 0 for a non-empty regular-file buffer; this signals the write could not complete — disk full, quota exceeded, or an I/O error surfaced as a short write.
Source
Thrown at eval/workflow_bench/promotion_apply.py:347
def _stage_replacement_at(parent_descriptor: int, content: bytes, mode: int) -> str:
for _ in range(100):
name = f".wfevolve-{secrets.token_hex(16)}"
try:
descriptor = os.open(
name,
os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_CLOEXEC", 0),
stat.S_IMODE(mode),
dir_fd=parent_descriptor,
)
except FileExistsError:
continue
try:
os.fchmod(descriptor, stat.S_IMODE(mode))
view = memoryview(content)
while view:
written = os.write(descriptor, view)
if written <= 0:
raise OSError("short write while staging overlay replacement")
view = view[written:]
os.fsync(descriptor)
except BaseException as exc:
os.close(descriptor)
try:
os.unlink(name, dir_fd=parent_descriptor)
os.fsync(parent_descriptor)
except OSError as cleanup_exc:
raise _StagingCleanupError(name, exc, cleanup_exc) from exc
raise
else:
os.close(descriptor)
try:
os.fsync(parent_descriptor)
except OSError as exc:
try:
os.unlink(name, dir_fd=parent_descriptor)
os.fsync(parent_descriptor)View on GitHub (pinned to d540b00184)
Solutions
- Check free space on the filesystem holding the checkout: `shutil.disk_usage(root)`.
- Free space or raise quota; move the checkout to a larger volume.
- Catch `OSError` and surface it — the module already unlinks the partial staging file and re-raises.
Example fix
// before
# staged write fails with ENOSPC
apply_promoted_overlay(overlay, repo_root=root)
// after
free = shutil.disk_usage(root).free
need = sum(len(c) for _, c in candidate_overlay_payload(overlay)[1]) * 3 # candidate + backup + headroom
if free < need:
raise SystemExit(f'insufficient free space: {free} < {need}')
apply_promoted_overlay(overlay, repo_root=root) Defensive patterns
Strategy: try-catch
Validate before calling
import shutil
free = shutil.disk_usage(root).free
need = sum(len(c) for _, c in candidate_overlay_payload(overlay)[1]) * 3
if free < need:
raise SystemExit(f'need ~{need} bytes free, have {free}') Try / catch
except OSError as exc:
if 'short write while staging' in str(exc):
raise SystemExit(f'staging write incomplete (disk full / I/O error): {exc}') from exc Prevention
- Ensure ample free space (>= 3x total overlay bytes) before promoting.
- Run promotion on a local disk with generous headroom, not a tiny tmpfs.
- Catch and report `OSError('short write ...')` as an environment fault.
When it happens
Trigger: Staging a replacement content buffer whose `os.write` returns 0 or negative: out of space on the filesystem holding the parent dir, quota hit, or a failing disk.
Common situations: CI runner out of disk; small tmpfs for the checkout; user quota exceeded; failing/read-only filesystem; overly large overlay payload near the 4 MiB `MAX_CANDIDATE_OVERLAY_BYTES` cap.
Related errors
- short write while staging candidate overlay
- could not allocate a unique overlay staging file
- short write while neutralizing {name}
- PdgEmitSink: ${errors.length} streamed CSV writer(s) hit an
- candidate destination parent must be a real directory: {rela
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/f426ea5463a4c057.
Report an issue: GitHub.