{"record":{"id":"e925a3856c4cd0fd","repo":"abhigyanpatwari/GitNexus","slug":"sandbox-copy-declarations-overlap-path-and-oth","errorCode":null,"errorMessage":"sandbox_copy declarations overlap: {path} and {other}","messagePattern":"sandbox_copy declarations overlap: (.+?) and (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/task_assets.py","lineNumber":557,"sourceCode":"\ndef _sandbox_copy_declarations(\n    task: Mapping[str, Any],\n) -> tuple[tuple[str, ...], tuple[PurePosixPath, ...]]:\n    raw_declarations = task.get(\"sandbox_copy\", [])\n    if not isinstance(raw_declarations, list) or not all(isinstance(item, str) and item for item in raw_declarations):\n        raise SandboxError(\"sandbox_copy must be a list of nonblank repository-relative paths\")\n    declarations = tuple(raw_declarations)\n    paths: list[PurePosixPath] = []\n    for raw in declarations:\n        relative = PurePosixPath(raw)\n        if relative.is_absolute() or not relative.parts or \"..\" in relative.parts:\n            raise SandboxError(f\"sandbox_copy must be a repository-relative path: {raw!r}\")\n        _validate_manifest_path(relative)\n        paths.append(relative)\n    for index, path in enumerate(paths):\n        for other in paths[index + 1 :]:\n            if path == other or path in other.parents or other in path.parents:\n                raise SandboxError(f\"sandbox_copy declarations overlap: {path} and {other}\")\n    return declarations, tuple(paths)\n\n\ndef _sandbox_dependency_declarations(\n    task: Mapping[str, Any],\n) -> tuple[_DependencyDeclaration, ...]:\n    raw_declarations = task.get(\"sandbox_dependencies\", [])\n    if not isinstance(raw_declarations, list):\n        raise SandboxError(\"sandbox_dependencies must be a list\")\n    declarations: list[_DependencyDeclaration] = []\n    for item in raw_declarations:\n        if (\n            not isinstance(item, Mapping)\n            or set(item) != {\"source\", \"target\"}\n            or not all(isinstance(item[field], str) and item[field] for field in (\"source\", \"target\"))\n        ):\n            raise SandboxError(\"sandbox_dependencies entries require only nonblank source and target\")\n        source = str(item[\"source\"])","sourceCodeStart":539,"sourceCodeEnd":575,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/task_assets.py#L539-L575","documentation":"Raised by _sandbox_copy_declarations during a pairwise comparison of all declared paths: if any two are equal, or one is an ancestor (parent) of the other, the declarations overlap and are rejected. Overlapping declarations would cause the snapshot builder to record the same bytes twice or contest directory ownership, so the harness requires a non-overlapping set. The check is O(n^2) but n is small for legitimate task declarations.","triggerScenarios":"Declaring both `repo/src` and `repo/src/lib` (parent + child), declaring the same path twice (`repo/src` and `repo/src`), or declaring `repo/src` and `repo/src` under different string spellings that PurePosixPath normalizes equal. Also `a/b` and `a/b/c`.","commonSituations":"Incrementally adding paths to a task without checking the existing set. Copying declarations from another task and merging. Syntactic duplicates from templating (`./src` and `src` normalize equal, so duplicates are caught, but a human may not realize).","solutions":["De-duplicate and de-nest the sandbox_copy list so no entry is an ancestor of another: prefer the broadest single root per area.","If you need both a broad root and a specific file under it, declare only the broad root — the child is captured automatically.","Sort and review declarations: `sorted(set(paths))` then check each pair.","Validate with the provided overlap guard before calling prepare() (see validationCode)."],"exampleFix":"// before\n{\"sandbox_copy\": [\"src\", \"src/lib\", \"src\", \"tests\"]}\n\n// after — drop nested and duplicate\n{\"sandbox_copy\": [\"src\", \"tests\"]}","handlingStrategy":"validation","validationCode":"from pathlib import PurePosixPath\n\ndef validate_no_copy_overlap(task: dict) -> None:\n    paths = [PurePosixPath(p) for p in task.get(\"sandbox_copy\", [])]\n    for i, a in enumerate(paths):\n        for b in paths[i+1:]:\n            if a == b or a in b.parents or b in a.parents:\n                raise ValueError(f\"sandbox_copy declarations overlap: {a} and {b}\")\n\nvalidate_no_copy_overlap(task)","typeGuard":"from pathlib import PurePosixPath\n\ndef copy_set_is_disjoint(paths: list[str]) -> bool:\n    ps = [PurePosixPath(p) for p in paths]\n    for i, a in enumerate(ps):\n        for b in ps[i+1:]:\n            if a == b or a in b.parents or b in a.parents:\n                return False\n    return True","tryCatchPattern":"from eval.workflow_bench.propposer_sandbox import SandboxError\n\ntry:\n    snapshot = cache.prepare(task, repo=repo, resolved_sha=sha)\nexcept SandboxError as exc:\n    if \"declarations overlap\" in str(exc):\n        # drop nested or duplicate entries from sandbox_copy\n        raise\n    raise","preventionTips":["De-duplicate and de-nest sandbox_copy at authoring time.","Declare only the broadest root per area; children are captured automatically.","Sort and visually review the declaration list before running the benchmark."],"tags":["sandbox","config","validation","overlap","task-declaration"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}