{"record":{"id":"f426ea5463a4c057","repo":"abhigyanpatwari/GitNexus","slug":"short-write-while-staging-overlay-replacement","errorCode":null,"errorMessage":"short write while staging overlay replacement","messagePattern":"short write while staging overlay replacement","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/promotion_apply.py","lineNumber":347,"sourceCode":"def _stage_replacement_at(parent_descriptor: int, content: bytes, mode: int) -> str:\n    for _ in range(100):\n        name = f\".wfevolve-{secrets.token_hex(16)}\"\n        try:\n            descriptor = os.open(\n                name,\n                os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, \"O_CLOEXEC\", 0),\n                stat.S_IMODE(mode),\n                dir_fd=parent_descriptor,\n            )\n        except FileExistsError:\n            continue\n        try:\n            os.fchmod(descriptor, stat.S_IMODE(mode))\n            view = memoryview(content)\n            while view:\n                written = os.write(descriptor, view)\n                if written <= 0:\n                    raise OSError(\"short write while staging overlay replacement\")\n                view = view[written:]\n            os.fsync(descriptor)\n        except BaseException as exc:\n            os.close(descriptor)\n            try:\n                os.unlink(name, dir_fd=parent_descriptor)\n                os.fsync(parent_descriptor)\n            except OSError as cleanup_exc:\n                raise _StagingCleanupError(name, exc, cleanup_exc) from exc\n            raise\n        else:\n            os.close(descriptor)\n            try:\n                os.fsync(parent_descriptor)\n            except OSError as exc:\n                try:\n                    os.unlink(name, dir_fd=parent_descriptor)\n                    os.fsync(parent_descriptor)","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/promotion_apply.py#L329-L365","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n# staged write fails with ENOSPC\napply_promoted_overlay(overlay, repo_root=root)\n// after\nfree = shutil.disk_usage(root).free\nneed = sum(len(c) for _, c in candidate_overlay_payload(overlay)[1]) * 3  # candidate + backup + headroom\nif free < need:\n    raise SystemExit(f'insufficient free space: {free} < {need}')\napply_promoted_overlay(overlay, repo_root=root)","handlingStrategy":"try-catch","validationCode":"import shutil\nfree = shutil.disk_usage(root).free\nneed = sum(len(c) for _, c in candidate_overlay_payload(overlay)[1]) * 3\nif free < need:\n    raise SystemExit(f'need ~{need} bytes free, have {free}')","typeGuard":null,"tryCatchPattern":"except OSError as exc:\n    if 'short write while staging' in str(exc):\n        raise SystemExit(f'staging write incomplete (disk full / I/O error): {exc}') from exc","preventionTips":["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."],"tags":["filesystem","disk-full","io-error","staging","overlay"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}