{"record":{"id":"7a5e7a033d8f41e8","repo":"abhigyanpatwari/GitNexus","slug":"read-only-sandbox-path-is-unavailable-raw-path","errorCode":null,"errorMessage":"read-only sandbox path is unavailable: {raw_path}","messagePattern":"read-only sandbox path is unavailable: (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/proposer_sandbox.py","lineNumber":129,"sourceCode":"    ) -> list[str]:\n        \"\"\"Build a stricter command boundary from this session's fixed roots.\n\n        Model sessions use ``read_only_paths`` to freeze the evaluated skill\n        roots. Verifiers use ``read_only_workspace`` so candidate-authored code\n        cannot change the credited implementation. Extra mounts are reserved\n        for harness-owned, post-session evidence such as hidden oracles.\n        \"\"\"\n\n        additional: list[ReadOnlyMount] = []\n        clone = _real_directory(self.clone, label=\"sandbox clone\")\n        for raw_path in read_only_paths:\n            lexical = raw_path.expanduser().absolute()\n            try:\n                relative = lexical.relative_to(clone)\n                metadata = lexical.lstat()\n                resolved = lexical.resolve(strict=True)\n            except (OSError, ValueError) as exc:\n                raise SandboxError(f\"read-only sandbox path is unavailable: {raw_path}\") from exc\n            if (\n                resolved != lexical\n                or stat.S_ISLNK(metadata.st_mode)\n                or not (stat.S_ISDIR(metadata.st_mode) or stat.S_ISREG(metadata.st_mode))\n            ):\n                raise SandboxError(f\"read-only sandbox path must be real and non-symlink: {raw_path}\")\n            additional.append(\n                ReadOnlyMount(\n                    source=lexical,\n                    target=f\"{SANDBOX_WORKSPACE}/{PurePosixPath(relative.as_posix())}\",\n                )\n            )\n\n        for mount in extra_read_only_mounts:\n            source = mount.source.expanduser().absolute()\n            try:\n                metadata = source.lstat()\n                resolved = source.resolve(strict=True)","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/proposer_sandbox.py#L111-L147","documentation":"Thrown by `command_prefix_for` when a path in `read_only_paths` cannot be resolved relative to the sandbox clone. The probe does `expanduser().absolute()`, then `relative_to(clone)`, `lstat()`, and `resolve(strict=True)`; any `OSError` or `ValueError` is wrapped as this `SandboxError`.","triggerScenarios":"Calling `session.command_prefix_for(read_only_paths=[...])` with a path that does not exist, is outside the clone (raises `ValueError` from `relative_to`), cannot be `lstat`-ed (permissions), or fails `resolve(strict=True)` (broken symlink, missing link in chain).","commonSituations":"Passing an absolute host path that is not under the sandbox clone; a typo in the path; the file was deleted between clone and probe; permissions on a parent dir prevent lstat; a path from another worktree.","solutions":["Ensure every `read_only_paths` entry exists and lives under `session.clone` (the harness root).","Resolve the path yourself first: `p = p.expanduser().resolve(strict=True)` and confirm `p.is_relative_to(session.clone)`.","Check permissions on every parent of the path so `lstat` succeeds.","If the path is supposed to live outside the clone, pass it via `extra_read_only_mounts` instead."],"exampleFix":"# before: absolute host path outside the clone\nprefix = session.command_prefix_for(read_only_paths=[Path('/etc/oracle.json')])  # -> SandboxError\n# after: place the file inside the clone, or use extra_read_only_mounts\nsession.clone.joinpath('oracle.json').write_text('...')\nprefix = session.command_prefix_for(read_only_paths=[session.clone / 'oracle.json'])","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef read_only_path_is_valid(clone: Path, raw_path: Path) -> bool:\n    try:\n        lexical = raw_path.expanduser().absolute()\n        _ = lexical.relative_to(clone)\n        lexical.lstat()\n        lexical.resolve(strict=True)\n    except (OSError, ValueError):\n        return False\n    return True\n\n# filter before building the prefix\nvalid = [p for p in read_only_paths if read_only_path_is_valid(session.clone, p)]\nprefix = session.command_prefix_for(read_only_paths=valid)","typeGuard":"from pathlib import Path\n\ndef is_real_path_under_clone(clone: Path, p: Path) -> bool:\n    \"\"\"Type guard: p exists, is under clone, and is real.\"\"\"\n    try:\n        lexical = p.expanduser().absolute()\n        lexical.relative_to(clone)\n        meta = lexical.lstat()\n        resolved = lexical.resolve(strict=True)\n    except (OSError, ValueError):\n        return False\n    import stat\n    return (\n        resolved == lexical\n        and not stat.S_ISLNK(meta.st_mode)\n        and (stat.S_ISDIR(meta.st_mode) or stat.S_ISREG(meta.st_mode))\n    )","tryCatchPattern":"try:\n    prefix = session.command_prefix_for(read_only_paths=paths)\nexcept SandboxError as exc:\n    if \"read-only sandbox path is unavailable\" in str(exc):\n        # drop the bad path or move the file inside the clone\n        paths = [p for p in paths if read_only_path_is_valid(session.clone, p)]\n        prefix = session.command_prefix_for(read_only_paths=paths)\n    raise","preventionTips":["Only pass paths that live under `session.clone` and exist on disk.","Resolve and validate paths in your harness before calling `command_prefix_for`.","Use `extra_read_only_mounts` for anything outside the clone."],"tags":["sandbox","bwrap","path-validation","mount"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}