abhigyanpatwari/GitNexus · error · SandboxError
sandbox_copy parent must be a directory: {relative}
Error message
sandbox_copy parent must be a directory: {relative} What it means
Raised by _open_child when require_directory=True (set for every intermediate component by _open_relative) and os.stat shows the component is not a directory. This catches a regular file sitting where the walker needs to descend.
Source
Thrown at eval/workflow_bench/task_assets.py:632
os.close(current)
raise
def _open_child(
parent_descriptor: int,
name: str,
relative: PurePosixPath,
*,
require_directory: bool = False,
) -> int:
try:
metadata = os.stat(name, dir_fd=parent_descriptor, follow_symlinks=False)
except OSError as exc:
raise SandboxError(f"sandbox_copy path is unavailable: {relative}: {exc}") from exc
if stat.S_ISLNK(metadata.st_mode):
raise SandboxError(f"sandbox_copy must not traverse a symlink: {relative}")
if require_directory and not stat.S_ISDIR(metadata.st_mode):
raise SandboxError(f"sandbox_copy parent must be a directory: {relative}")
if not (stat.S_ISDIR(metadata.st_mode) or stat.S_ISREG(metadata.st_mode)):
raise SandboxError(f"sandbox_copy accepts only regular files and directories: {relative}")
flags = os.O_RDONLY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)
if stat.S_ISDIR(metadata.st_mode):
flags |= os.O_DIRECTORY
else:
flags |= getattr(os, "O_NONBLOCK", 0)
try:
descriptor = os.open(name, flags, dir_fd=parent_descriptor)
except OSError as exc:
raise SandboxError(f"sandbox_copy path changed or is unreadable: {relative}: {exc}") from exc
opened = os.fstat(descriptor)
if not (stat.S_ISDIR(opened.st_mode) or stat.S_ISREG(opened.st_mode)):
os.close(descriptor)
raise SandboxError(f"sandbox_copy accepts only regular files and directories: {relative}")
if (
opened.st_dev,
opened.st_ino,View on GitHub (pinned to d540b00184)
Solutions
- Confirm each intermediate component is a directory at the SHA: `git cat-file -e <sha>:<parent>/`
- Correct the declaration path so only the final component is a file
- Re-pin the task to a SHA whose layout matches the declaration
Defensive patterns
Strategy: validation
Validate before calling
import os
from pathlib import Path
def parents_are_dirs(root: Path, declared: list[str]) -> list[str]:
bad = []
for decl in declared:
parts = Path(decl).parts[:-1] # intermediate components only
walker = root
for part in parts:
walker = walker / part
try:
if not walker.is_dir():
bad.append(f"{decl}: {walker} is not a directory"); break
except OSError as exc:
bad.append(f"{decl}: {exc}"); break
return bad Try / catch
from eval.workflow_bench.proposer_sandbox import SandboxError
try:
snapshot = cache.prepare(task, repo=repo, resolved_sha=sha)
except SandboxError as exc:
if "parent must be a directory" in str(exc):
raise SystemExit(f"declaration path layout invalid: {exc}") from exc
raise Prevention
- Confirm every intermediate path component is a directory at the SHA before capture
- Re-pin tasks when a directory/file swap occurs in the repo layout
When it happens
Trigger: A declaration path like src/index.ts/utils where src/index.ts is a file; an intermediate name collides with an existing regular file; a directory was renamed to a file between pins.
Common situations: Renaming a directory to a file (or vice versa) between commit pins; typo'd declaration path that joins a filename with further children.
Related errors
- sandbox_copy path is unavailable: {relative}: {exc}
- sandbox_copy must not traverse a symlink: {relative}
- sandbox_copy {role}: {relative}
- sandbox_copy target has an unsupported type: {relative}
- sandbox_copy target parent has an unsupported type: {relativ
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/9fc3bec6ee51171c.
Report an issue: GitHub.