{"record":{"id":"f88587d2d8d86bed","repo":"abhigyanpatwari/GitNexus","slug":"sanitized-graph-source-changed-while-scanning-re","errorCode":null,"errorMessage":"sanitized graph source changed while scanning: {relative}","messagePattern":"sanitized graph source changed while scanning: (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/sanitized_graph.py","lineNumber":221,"sourceCode":"                    metadata.st_size,\n                ):\n                    raise SandboxError(f\"sanitized graph source changed while opening: {relative}\")\n                chunks: list[bytes] = []\n                remaining = MAX_GRAPH_SCRUB_FILE_BYTES + 1\n                while remaining > 0:\n                    chunk = os.read(descriptor, min(64 * 1024, remaining))\n                    if not chunk:\n                        break\n                    chunks.append(chunk)\n                    remaining -= len(chunk)\n                payload = b\"\".join(chunks)\n                after = os.fstat(descriptor)\n                if len(payload) != opened.st_size or (opened.st_size, opened.st_mtime_ns, opened.st_ctime_ns) != (\n                    after.st_size,\n                    after.st_mtime_ns,\n                    after.st_ctime_ns,\n                ):\n                    raise SandboxError(f\"sanitized graph source changed while scanning: {relative}\")\n            finally:\n                os.close(descriptor)\n            if any(marker in payload for marker in marker_bytes):\n                Path(entry.path).unlink()\n                removed.append(relative_text)\n    return tuple(sorted(removed))\n\n\ndef _graph_environment() -> dict[str, str]:\n    env = build_sandbox_environment()\n    env.update(\n        {\n            \"GITNEXUS_HOME\": SANDBOX_INDEX_REGISTRY,\n            \"GITNEXUS_NO_GITIGNORE\": \"1\",\n            \"GITNEXUS_WORKER_POOL_SIZE\": \"1\",\n            \"GITNEXUS_PARSE_CHUNK_CONCURRENCY\": \"1\",\n        }\n    )","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/sanitized_graph.py#L203-L239","documentation":"Second TOCTOU guard inside the file read: after streaming the file into a payload buffer, a final os.fstat shows st_size or (st_mtime_ns, st_ctime_ns) differs from the value taken at open, or the bytes read do not match the opened size. Indicates the file was truncated/extended/rewritten during the read.","triggerScenarios":"A file in the seed is appended to, truncated, or replaced while the scrubber reads it in 64 KiB chunks (up to MAX_GRAPH_SCRUB_FILE_BYTES + 1).","commonSituations":"Log files or generated outputs being written live in the worktree; concurrent git operations; a sync/indexing daemon touching files mid-scan.","solutions":["Quiesce the seed (no writers) for the duration of scrub and graph build.","Point volatile outputs (logs, generated artifacts) outside the worktree.","Retry once the writer is stopped; rebuild the seed via make_worktree."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import fcntl, os\n\ndef quiesce_seed(root):\n    \"\"\"Hold an exclusive lock so no writer mutates files during the read.\"\"\"\n    fd = os.open(root, os.O_RDONLY | os.O_DIRECTORY)\n    fcntl.flock(fd, fcntl.LOCK_EX)\n    return fd","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Quiesce the seed (no writers) for the duration of scrub and graph build.","Point volatile outputs (logs, generated artifacts) outside the worktree.","Retry once the writer is stopped; rebuild via make_worktree."],"tags":["sandbox","toctou","filesystem","workflow-bench"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}