abhigyanpatwari/GitNexus · error · SandboxError
sandbox_copy must be a list of nonblank repository-relative
Error message
sandbox_copy must be a list of nonblank repository-relative paths
What it means
Raised by _sandbox_copy_declarations when the task's `sandbox_copy` field is absent-as-non-list or is a list containing any element that is not a non-blank string. The field must be a list of repository-relative path strings, each truthy (non-empty after strip semantics of truthiness). This is the top-level schema gate for sandbox_copy declarations, evaluated before any path validation.
Source
Thrown at eval/workflow_bench/task_assets.py:545
def ensure_directory(self, relative: PurePosixPath) -> None:
"""Record and create one extra directory inside this snapshot.
Used for harness-owned mount points that must exist in the captured
bytes rather than be created against a read-only bind at runtime.
"""
self._record_directory(relative)
def finished_entries(self) -> tuple[AssetManifestEntry, ...]:
return tuple(sorted(self.entries.values(), key=lambda entry: entry.path.as_posix()))
def _sandbox_copy_declarations(
task: Mapping[str, Any],
) -> tuple[tuple[str, ...], tuple[PurePosixPath, ...]]:
raw_declarations = task.get("sandbox_copy", [])
if not isinstance(raw_declarations, list) or not all(isinstance(item, str) and item for item in raw_declarations):
raise SandboxError("sandbox_copy must be a list of nonblank repository-relative paths")
declarations = tuple(raw_declarations)
paths: list[PurePosixPath] = []
for raw in declarations:
relative = PurePosixPath(raw)
if relative.is_absolute() or not relative.parts or ".." in relative.parts:
raise SandboxError(f"sandbox_copy must be a repository-relative path: {raw!r}")
_validate_manifest_path(relative)
paths.append(relative)
for index, path in enumerate(paths):
for other in paths[index + 1 :]:
if path == other or path in other.parents or other in path.parents:
raise SandboxError(f"sandbox_copy declarations overlap: {path} and {other}")
return declarations, tuple(paths)
def _sandbox_dependency_declarations(
task: Mapping[str, Any],
) -> tuple[_DependencyDeclaration, ...]:View on GitHub (pinned to d540b00184)
Solutions
- Ensure `sandbox_copy` is a JSON list of non-empty strings: `["path/one", "path/two"]`.
- Validate the task document against the expected schema before passing it to prepare() (see validationCode).
- Omit the field entirely (`sandbox_copy: []` or absent) if no paths are needed — both are accepted.
- Strip whitespace and drop blanks at authoring time so no empty-string element reaches the harness.
Example fix
// before
{"sandbox_copy": "repo/src"}
// or
{"sandbox_copy": ["repo/src", "", null]}
// after
{"sandbox_copy": ["repo/src"]} Defensive patterns
Strategy: type-guard
Validate before calling
def validate_sandbox_copy_shape(task: dict) -> None:
raw = task.get("sandbox_copy", [])
if not isinstance(raw, list):
raise ValueError("sandbox_copy must be a list")
for item in raw:
if not isinstance(item, str) or not item:
raise ValueError(f"sandbox_copy entries must be nonblank strings, got {item!r}")
validate_sandbox_copy_shape(task) Type guard
from typing import Any
def is_sandbox_copy_list(value: Any) -> bool:
return (
isinstance(value, list)
and all(isinstance(item, str) and item for item in value)
) Try / catch
from eval.workflow_bench.propposer_sandbox import SandboxError
try:
snapshot = cache.prepare(task, repo=repo, resolved_sha=sha)
except SandboxError as exc:
if "must be a list of nonblank" in str(exc):
# fix the sandbox_copy field shape in the task document
raise
raise Prevention
- Always author sandbox_copy as a JSON array of non-empty strings, even for one path.
- Validate the task document against a schema (e.g. pydantic or jsonschema) before prepare.
- Omit the field or use [] when no paths are needed.
When it happens
Trigger: Task JSON has `"sandbox_copy": "src"` (a string, not a list), `"sandbox_copy": ["src", 123]` (mixed types), `"sandbox_copy": ["src", ""]` (blank element), `"sandbox_copy": ["src", null]`, or `"sandbox_copy": {"paths": [...]}` (a dict). The check is `isinstance(item, str) and item` for every element.
Common situations: Hand-writing task YAML/JSON and forgetting the list brackets. Copying a single-path shorthand from another tool that accepts a bare string. A serialization bug that emits None or empty strings for missing optional paths. Schema drift between task authoring and the harness contract.
Related errors
- sandbox_dependencies must be a list
- sandbox_dependencies entries require only nonblank source an
- sandbox_copy must be a repository-relative path: {raw!r}
- sandbox_copy declarations overlap: {path} and {other}
- dependency source must stay inside the repository: {source_p
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/4b5fa43a4c8565de.
Report an issue: GitHub.