{"record":{"id":"6815d690122f05c0","repo":"abhigyanpatwari/GitNexus","slug":"sandbox-copy-paths-collide-at-entry-path","errorCode":null,"errorMessage":"sandbox_copy paths collide at {entry.path}","messagePattern":"sandbox_copy paths collide at (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/task_assets.py","lineNumber":520,"sourceCode":"\n    def _ensure_parents(self, relative: PurePosixPath) -> None:\n        current = PurePosixPath()\n        for part in relative.parts:\n            current /= part\n            existing = self.entries.get(current)\n            if existing is not None:\n                if existing.kind != \"directory\":\n                    raise SandboxError(f\"sandbox_copy paths collide at {current}\")\n                continue\n            self._record(AssetManifestEntry(path=current, kind=\"directory\"))\n            (self.destination / Path(*current.parts)).mkdir(mode=0o700, exist_ok=True)\n\n    def _record(self, entry: AssetManifestEntry) -> None:\n        _validate_manifest_path(entry.path)\n        existing = self.entries.get(entry.path)\n        if existing is not None:\n            if existing != entry:\n                raise SandboxError(f\"sandbox_copy paths collide at {entry.path}\")\n            return\n        if self.budget.entries >= MAX_TASK_ASSET_ENTRIES:\n            raise SandboxError(\"sandbox_copy exceeds the entry limit\")\n        self.entries[entry.path] = entry\n        self.budget.entries += 1\n\n    def ensure_directory(self, relative: PurePosixPath) -> None:\n        \"\"\"Record and create one extra directory inside this snapshot.\n\n        Used for harness-owned mount points that must exist in the captured\n        bytes rather than be created against a read-only bind at runtime.\n        \"\"\"\n\n        self._record_directory(relative)\n\n    def finished_entries(self) -> tuple[AssetManifestEntry, ...]:\n        return tuple(sorted(self.entries.values(), key=lambda entry: entry.path.as_posix()))\n","sourceCodeStart":502,"sourceCodeEnd":538,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/task_assets.py#L502-L538","documentation":"Raised by _SnapshotBuilder._record when a manifest entry at a given path was already recorded with different fields (different kind, size, sha256, mode, or link_target). The second recording is rejected because the manifest must be deterministic — the same path cannot have two distinct captured identities in one snapshot. Identical re-recording is a no-op (the early `existing != entry` check returns).","triggerScenarios":"The same relative path is captured twice with differing metadata within one prepare() call. This can happen if a file is mutated between two traversals (so its sha256 differs), or if the path is reached via two different declaration roots whose trees overlap in a way the declaration-overlap check did not block (e.g. a dependency payload path colliding with a sandbox_copy path).","commonSituations":"Two sandbox_dependency sources that both contain a `payload/foo` resolved to the same snapshot path but with different contents. A concurrent mutation that changes a file's sha256 between the first and second time the builder visits it. A misconfigured declaration where sandbox_copy and a dependency target alias the same in-snapshot path.","solutions":["Review all sandbox_copy and sandbox_dependencies entries for paths that resolve to the same in-snapshot location; eliminate aliases.","Quiesce the source tree so a file visited twice yields identical sha256 (stop concurrent writers).","Ensure each dependency's source maps to a distinct snapshot_path (the harness uses indexed containers, so collision implies duplicate target declarations).","Run detect_changes or a tree diff to confirm the source is stable across the capture window."],"exampleFix":"// before — two deps target the same in-clone path with different sources\n{\"sandbox_dependencies\": [\n  {\"source\": \"a/node_modules\", \"target\": \"node_modules\"},\n  {\"source\": \"b/node_modules\", \"target\": \"node_modules\"}\n]}\n\n// after — distinct targets\n{\"sandbox_dependencies\": [\n  {\"source\": \"a/node_modules\", \"target\": \"node_modules\"}\n]}","handlingStrategy":"validation","validationCode":"from pathlib import PurePosixPath\n\ndef validate_distinct_in_snapshot_paths(copy_paths: list[PurePosixPath], dep_targets: list[PurePosixPath]) -> None:\n    \"\"\"Ensure no copy path aliases a dependency target and all targets are distinct.\"\"\"\n    seen = {}\n    for p in list(copy_paths) + list(dep_targets):\n        if p in seen:\n            raise ValueError(f\"duplicate in-snapshot path: {p}\")\n        seen[p] = True\n\nvalidate_distinct_in_snapshot_paths(\n    [PurePosixPath(p) for p in task[\"sandbox_copy\"]],\n    [PurePosixPath(d[\"target\"]) for d in task.get(\"sandbox_dependencies\", [])],\n)","typeGuard":null,"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 \"paths collide\" in str(exc):\n        # two declarations resolve to the same in-snapshot path with different content\n        raise\n    raise","preventionTips":["Ensure each sandbox_dependency target is distinct and does not alias a sandbox_copy path.","Quiesce the tree so a file visited twice yields identical sha256.","Avoid declaring the same source under two dependency targets."],"tags":["sandbox","manifest","validation","collision","integrity"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}