abhigyanpatwari/GitNexus · error · SandboxError
sandbox_copy must be a list
Error message
sandbox_copy must be a list
What it means
Type guard in validate_no_prebuilt_graph_assets. The task spec's 'sandbox_copy' field must be a list; anything else (a string, a mapping, null with a non-default sentinel) is rejected because the harness cannot iterate it safely and a malformed value could hide a restricted path. The default is an empty list, so omitting the field is fine.
Source
Thrown at eval/workflow_bench/sanitized_graph.py:89
)
self.assets.materialize(clone)
def _is_restricted_path(value: str) -> bool:
relative = PurePosixPath(value)
if relative.is_absolute() or not relative.parts or ".." in relative.parts:
return False
return (
relative.parts[0] == ".gitnexus" or relative == HIDDEN_HARNESS_PATH or HIDDEN_HARNESS_PATH in relative.parents
)
def validate_no_prebuilt_graph_assets(task: Mapping[str, Any]) -> None:
"""Reject declarations that could reintroduce an unsanitized graph/oracle."""
sandbox_copy = task.get("sandbox_copy", [])
if not isinstance(sandbox_copy, list):
raise SandboxError("sandbox_copy must be a list")
for value in sandbox_copy:
if isinstance(value, str) and _is_restricted_path(value):
raise SandboxError(f"sandbox_copy cannot import prebuilt graph or harness data: {value}")
dependencies = task.get("sandbox_dependencies", [])
if not isinstance(dependencies, list):
raise SandboxError("sandbox_dependencies must be a list")
for item in dependencies:
if not isinstance(item, Mapping):
continue
for field in ("source", "target"):
value = item.get(field)
if isinstance(value, str) and _is_restricted_path(value):
raise SandboxError(f"sandbox dependency cannot expose prebuilt graph or harness data: {value}")
def _replace_control_file(root: Path, name: str, payload: bytes) -> None:
path = root / nameView on GitHub (pinned to d540b00184)
Solutions
- Make sandbox_copy a sequence in the task spec: 'sandbox_copy: ["path/one", "path/two"]' or YAML block list with each entry a string.
- If you intended a single copy, still wrap it in a list: 'sandbox_copy: ["path/one"]'.
- Validate the task file locally: load it and assert isinstance(spec.get('sandbox_copy', []), list) before running.
- Check the task schema documentation for the current expected shape of sandbox_copy.
Example fix
# before (tasks.scenarios.yaml) sandbox_copy: src/fixtures/oracle.json # after sandbox_copy: - src/fixtures/oracle.json
Defensive patterns
Strategy: type-guard
Validate before calling
import yaml
from pathlib import Path
task = yaml.safe_load(Path("task.yaml").read_text())
if "sandbox_copy" in task and not isinstance(task["sandbox_copy"], list):
raise SystemExit(f"sandbox_copy must be a list, got {type(task['sandbox_copy']).__name__}")
# validate_no_prebuilt_graph_assets(task) # full harness check Type guard
from collections.abc import Mapping
def sandbox_copy_well_formed(task: Mapping) -> bool:
sc = task.get("sandbox_copy", [])
return isinstance(sc, list) and all(isinstance(v, str) for v in sc) Try / catch
from eval.workflow_bench.sanitized_graph import validate_no_prebuilt_graph_assets, SandboxError
try:
validate_no_prebuilt_graph_assets(task)
except SandboxError as exc:
if "sandbox_copy must be a list" in str(exc):
log.error("task.sandbox_copy must be a YAML/JSON list of strings")
raise Prevention
- Always declare sandbox_copy as a sequence, even for one entry.
- Lint task specs in CI with a schema that requires sandbox_copy to be an array of strings.
- Run validate_no_prebuilt_graph_assets on every task before submission.
When it happens
Trigger: A task YAML/JSON declares sandbox_copy as a scalar (e.g. 'sandbox_copy: .gitnexus/oracle.json') or as a mapping instead of a sequence of strings. validate_no_prebuilt_graph_assets runs the isinstance check before scanning entries.
Common situations: Author typo (single value instead of one-element list); a YAML parser turning an unquoted special value into a non-string scalar; schema drift after a task-format change; copy-pasting a dependency-style mapping into sandbox_copy.
Related errors
- sandbox_dependencies must be a list
- {label} is unavailable: {path}: {exc}
- {label} must be a real non-symlink directory: {path}
- {label} contains an unsafe path component: {relative}
- {label} is unreadable: {path}: {exc}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/a1fbac82819ba4d9.
Report an issue: GitHub.