abhigyanpatwari/GitNexus · error · SandboxError

cannot scan sanitized graph source: {directory}: {exc}

Error message

cannot scan sanitized graph source: {directory}: {exc}

What it means

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}.

Source

Thrown at eval/workflow_bench/sanitized_graph.py:168

    The disposable graph seed may contain docs or shipped skill copies outside
    the removed harness that name its paths. They are harmless implementation
    context in an arm checkout, but indexing them would let graph/MCP queries
    recover benchmark-specific hints. Scan the exact <=512 KiB file universe
    admitted by the pinned analyzer and remove contaminated inputs before the
    graph is built. Target-controlled ignore/config files are not consulted.
    """

    marker_bytes = tuple(marker.encode() for marker in GRAPH_MARKERS)
    pending: list[tuple[Path, PurePosixPath]] = [(root, PurePosixPath())]
    removed: list[str] = []
    entries = 0
    scanned_bytes = 0
    while pending:
        directory, relative_directory = pending.pop()
        try:
            children = sorted(os.scandir(directory), key=lambda item: item.name, reverse=True)
        except OSError as exc:
            raise SandboxError(f"cannot scan sanitized graph source: {directory}: {exc}") from exc
        for entry in children:
            relative = relative_directory / entry.name
            if relative.parts[0] in {".git", ".gitnexus"}:
                continue
            entries += 1
            if entries > MAX_GRAPH_SCRUB_ENTRIES:
                raise SandboxError("sanitized graph source exceeds the scrub entry limit")
            relative_text = relative.as_posix()
            metadata = entry.stat(follow_symlinks=False)
            path_matches = any(marker in relative_text for marker in GRAPH_MARKERS)
            if path_matches:
                path = Path(entry.path)
                if stat.S_ISDIR(metadata.st_mode) and not stat.S_ISLNK(metadata.st_mode):
                    shutil.rmtree(path)
                else:
                    path.unlink()
                removed.append(relative_text)
                continue

View on GitHub (pinned to d540b00184)

Solutions

  1. Inspect the chained __cause__ OSError.errno (EACCES vs EIO vs ENOENT) to localize the fault.
  2. Ensure the runner owns the seed worktree and that the worktree root is on a reliable local filesystem, not a network/9p mount.
  3. Confirm no concurrent process (another arm, a stale cleaner, an IDE/git watcher) is deleting directories under the seed during scrub.
  4. Re-run prepare_sanitized_graph after the filesystem/mount issue is resolved; the seed is disposable and rebuilt via make_worktree.
Defensive patterns

Strategy: try-catch

Validate before calling

import os

def assert_scrubbable(root):
    """Pre-walk to confirm every directory is scandir-able before scrubbing."""
    for dirpath, dirnames, _ in os.walk(root):
        try:
            os.scandir(dirpath).close()
        except OSError as exc:
            raise RuntimeError(f"unreadable before scrub: {dirpath}: {exc}") from exc

Try / catch

from workflow_bench.proposer_sandbox import SandboxError

try:
    prepare_sanitized_graph(task, repo=repo, resolved_sha=sha, ...)
except SandboxError as exc:
    cause = exc.__cause__
    errno = getattr(cause, "errno", None)
    log.error("graph scrub failed: %s (errno=%s)", exc, errno)
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/fbe936600183ee59. Report an issue: GitHub.