{"record":{"id":"fbe936600183ee59","repo":"abhigyanpatwari/GitNexus","slug":"cannot-scan-sanitized-graph-source-directory","errorCode":null,"errorMessage":"cannot scan sanitized graph source: {directory}: {exc}","messagePattern":"cannot scan sanitized graph source: (.+?): (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/sanitized_graph.py","lineNumber":168,"sourceCode":"    The disposable graph seed may contain docs or shipped skill copies outside\n    the removed harness that name its paths. They are harmless implementation\n    context in an arm checkout, but indexing them would let graph/MCP queries\n    recover benchmark-specific hints. Scan the exact <=512 KiB file universe\n    admitted by the pinned analyzer and remove contaminated inputs before the\n    graph is built. Target-controlled ignore/config files are not consulted.\n    \"\"\"\n\n    marker_bytes = tuple(marker.encode() for marker in GRAPH_MARKERS)\n    pending: list[tuple[Path, PurePosixPath]] = [(root, PurePosixPath())]\n    removed: list[str] = []\n    entries = 0\n    scanned_bytes = 0\n    while pending:\n        directory, relative_directory = pending.pop()\n        try:\n            children = sorted(os.scandir(directory), key=lambda item: item.name, reverse=True)\n        except OSError as exc:\n            raise SandboxError(f\"cannot scan sanitized graph source: {directory}: {exc}\") from exc\n        for entry in children:\n            relative = relative_directory / entry.name\n            if relative.parts[0] in {\".git\", \".gitnexus\"}:\n                continue\n            entries += 1\n            if entries > MAX_GRAPH_SCRUB_ENTRIES:\n                raise SandboxError(\"sanitized graph source exceeds the scrub entry limit\")\n            relative_text = relative.as_posix()\n            metadata = entry.stat(follow_symlinks=False)\n            path_matches = any(marker in relative_text for marker in GRAPH_MARKERS)\n            if path_matches:\n                path = Path(entry.path)\n                if stat.S_ISDIR(metadata.st_mode) and not stat.S_ISLNK(metadata.st_mode):\n                    shutil.rmtree(path)\n                else:\n                    path.unlink()\n                removed.append(relative_text)\n                continue","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/sanitized_graph.py#L150-L186","documentation":"Raised by _scrub_source_references when os.scandir on a directory inside the disposable graph seed raises OSError; it is wrapped as a SandboxError that fails containment closed. The scrubber must enumerate every directory to prove no benchmark-harness references survive into the graph, so an unreadable directory aborts the whole build. The original OSError is chained via 'raise ... from exc' and its message is interpolated into {exc}.","triggerScenarios":"Calling prepare_sanitized_graph (which calls _scrub_source_references) when the seed worktree contains a directory os.scandir cannot enumerate: EACCES on the runner UID, EIO/ENOTCONN on a flaky 9p/NFS/overlay mount, ENOENT because the dir was removed mid-walk, or ELOOP.","commonSituations":"Running workflow_bench in a container where the worktree sits on a 9p or overlay mount that intermittently returns IO errors; the benchmark runner lacks permissions on the clone; a prior cleanup raced and removed a directory during scrub.","solutions":["Inspect the chained __cause__ OSError.errno (EACCES vs EIO vs ENOENT) to localize the fault.","Ensure the runner owns the seed worktree and that the worktree root is on a reliable local filesystem, not a network/9p mount.","Confirm no concurrent process (another arm, a stale cleaner, an IDE/git watcher) is deleting directories under the seed during scrub.","Re-run prepare_sanitized_graph after the filesystem/mount issue is resolved; the seed is disposable and rebuilt via make_worktree."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import os\n\ndef assert_scrubbable(root):\n    \"\"\"Pre-walk to confirm every directory is scandir-able before scrubbing.\"\"\"\n    for dirpath, dirnames, _ in os.walk(root):\n        try:\n            os.scandir(dirpath).close()\n        except OSError as exc:\n            raise RuntimeError(f\"unreadable before scrub: {dirpath}: {exc}\") from exc","typeGuard":null,"tryCatchPattern":"from workflow_bench.proposer_sandbox import SandboxError\n\ntry:\n    prepare_sanitized_graph(task, repo=repo, resolved_sha=sha, ...)\nexcept SandboxError as exc:\n    cause = exc.__cause__\n    errno = getattr(cause, \"errno\", None)\n    log.error(\"graph scrub failed: %s (errno=%s)\", exc, errno)\n    raise","preventionTips":["Run the benchmark on a local ext4/tmpfs worktree, never on a network or 9p mount.","Ensure single-writer access to the seed during the scrub window.","Pre-validate the clone is readable by the runner UID before invoking prepare_sanitized_graph."],"tags":["sandbox","filesystem","workflow-bench","io"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}