{"record":{"id":"2ad052620d063c9b","repo":"abhigyanpatwari/GitNexus","slug":"workspace-file-changed-while-hashing-entry-path","errorCode":null,"errorMessage":"workspace file changed while hashing: {entry.path}","messagePattern":"workspace file changed while hashing: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/runner_artifacts.py","lineNumber":181,"sourceCode":"                continue\n            file_bytes += metadata.st_size\n            if file_bytes > MAX_WORKSPACE_SNAPSHOT_FILE_BYTES:\n                raise ValueError(\"workspace snapshot exceeds its bounded file-byte limit\")\n            descriptor = os.open(entry.path, os.O_RDONLY | nofollow)\n            try:\n                opened = os.fstat(descriptor)\n                if (\n                    not stat.S_ISREG(opened.st_mode)\n                    or opened.st_dev != metadata.st_dev\n                    or opened.st_ino != metadata.st_ino\n                ):\n                    raise ValueError(f\"workspace file changed while opening: {entry.path}\")\n                digest = hashlib.sha256()\n                while chunk := os.read(descriptor, 64 * 1024):\n                    digest.update(chunk)\n                after = os.fstat(descriptor)\n                if (opened.st_size, opened.st_mtime_ns) != (after.st_size, after.st_mtime_ns):\n                    raise ValueError(f\"workspace file changed while hashing: {entry.path}\")\n            finally:\n                os.close(descriptor)\n            snapshot[relative.as_posix()] = f\"f:{permissions:o}:{metadata.st_size}:{digest.hexdigest()}\"\n    return snapshot\n\n\ndef enforce_phase_workspace(\n    worktree: Path,\n    before: dict[str, str],\n    *,\n    allowed_artifact: Path,\n) -> None:\n    \"\"\"Require a phase to change only its one explicit workspace artifact.\"\"\"\n\n    root = worktree.expanduser().absolute()\n    artifact = allowed_artifact.expanduser().absolute()\n    try:\n        relative = PurePosixPath(artifact.relative_to(root).as_posix())","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/runner_artifacts.py#L163-L199","documentation":"Raised in workspace_snapshot (runner_artifacts.py:181) after hashing a file: os.fstat is taken again and if size or mtime_ns changed between the pre-hash fstat and the post-hash fstat the file is considered mutated during hashing. The guard ensures the computed sha256 actually corresponds to stable content; a mid-read change would yield a meaningless hash.","triggerScenarios":"A process writes to the file while os.read loops over its 64 KiB chunks: between the pre-read fstat (line 169) and the post-read fstat (line 179) either st_size or st_mtime_ns differs. Happens when a log file, build output, or model artifact is appended to during the snapshot.","commonSituations":"A task is still writing logs/output when the phase-boundary snapshot runs; an editor autosaving; a daemon appending to a file inside the worktree; concurrent arms sharing a directory they should not.","solutions":["Ensure the phase is quiescent before snapshotting — the model/build must have exited and flushed. Check for stray processes writing to the worktree (lsof +D <worktree>).","If the file is a live log, exclude it by moving it under a bootstrap-noise path or out of the worktree.","Re-run the snapshot; transient concurrency races usually clear once the writer is gone."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    snapshot = workspace_snapshot(root)\nexcept ValueError as exc:\n    if \"changed while hashing\" in str(exc):\n        # File was appended/truncated during the read loop.\n        wait_for_quiescence(root)\n        snapshot = workspace_snapshot(root)\n    else:\n        raise","preventionTips":["Ensure no log/daemon is appending to files in the worktree during the snapshot.","Move live logs outside the hashed tree.","Take the snapshot at a true phase boundary where the writer has exited."],"tags":["toctou","integrity","workspace-snapshot"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}