abhigyanpatwari/GitNexus · error · SandboxError
extra read-only mount must be real and non-symlink: {source}
Error message
extra read-only mount must be real and non-symlink: {source} What it means
Thrown by `command_prefix_for` after an `extra_read_only_mounts` source was probed successfully but failed the 'real and non-symlink' check: resolved != lexical, `lstat` reports a symlink, or the entry is neither directory nor regular file. The same constraint as error 416, applied to extra mount sources.
Source
Thrown at eval/workflow_bench/proposer_sandbox.py:155
ReadOnlyMount(
source=lexical,
target=f"{SANDBOX_WORKSPACE}/{PurePosixPath(relative.as_posix())}",
)
)
for mount in extra_read_only_mounts:
source = mount.source.expanduser().absolute()
try:
metadata = source.lstat()
resolved = source.resolve(strict=True)
except OSError as exc:
raise SandboxError(f"extra read-only mount is unavailable: {source}") from exc
if (
resolved != source
or stat.S_ISLNK(metadata.st_mode)
or not (stat.S_ISDIR(metadata.st_mode) or stat.S_ISREG(metadata.st_mode))
):
raise SandboxError(f"extra read-only mount must be real and non-symlink: {source}")
target = PurePosixPath(mount.target)
if not target.is_absolute() or ".." in target.parts:
raise SandboxError(f"extra read-only mount target must be absolute: {mount.target}")
additional.append(ReadOnlyMount(source=source, target=target.as_posix()))
return _sandbox_command_prefix(
bwrap=self.bwrap_bin,
clone=clone,
home=self.home,
temp=self.temp,
claude_bin=self.claude_host_bin,
mounts=(*self.read_only_mounts, *additional),
read_only_workspace=read_only_workspace,
unshare_network=unshare_network,
)
_TOKEN_PATTERNS = (View on GitHub (pinned to d540b00184)
Solutions
- Dereference the source: `source = ReadOnlyMount(source=p.resolve(strict=True), target=t)`.
- Write evidence as a regular file (not a symlink) and freeze that path.
- Filter: `assert (p.is_dir() or p.is_file()) and not p.is_symlink()` before constructing the mount.
- If the source is a symlinked directory by design, replace it with a real directory.
Example fix
# before: oracle is a symlink
mount = ReadOnlyMount(source=Path('/evidence/oracle'), target='/workspace/oracle.json')
# /evidence/oracle -> /shared/oracle (symlink)
prefix = session.command_prefix_for(extra_read_only_mounts=[mount]) # -> SandboxError
# after: bind the resolved real path
mount = ReadOnlyMount(
source=Path('/evidence/oracle').resolve(strict=True),
target='/workspace/oracle.json',
)
prefix = session.command_prefix_for(extra_read_only_mounts=[mount]) Defensive patterns
Strategy: validation
Validate before calling
import stat
from pathlib import Path
def is_real_nonsymlink_path(p: Path) -> bool:
try:
source = p.expanduser().absolute()
meta = source.lstat()
resolved = source.resolve(strict=True)
except OSError:
return False
return (
resolved == source
and not stat.S_ISLNK(meta.st_mode)
and (stat.S_ISDIR(meta.st_mode) or stat.S_ISREG(meta.st_mode))
) Type guard
import stat
from pathlib import Path
def is_freezable_extra_mount_source(p: Path) -> bool:
return is_real_nonsymlink_path(p) Try / catch
try:
prefix = session.command_prefix_for(extra_read_only_mounts=mounts)
except SandboxError as exc:
if "extra read-only mount must be real and non-symlink" in str(exc):
# dereference symlinks, drop non-regular entries
mounts = [
ReadOnlyMount(source=m.source.resolve(strict=True), target=m.target)
for m in mounts
if is_real_nonsymlink_path(m.source.resolve(strict=True))
]
prefix = session.command_prefix_for(extra_read_only_mounts=mounts)
raise Prevention
- Always `resolve(strict=True)` extra mount sources before constructing `ReadOnlyMount`.
- Write evidence as regular files, never symlinks or sockets.
- Validate `not p.is_symlink() and (p.is_dir() or p.is_file())` in your harness.
When it happens
Trigger: An `extra_read_only_mounts` source that is a symlink, resolves through a symlink chain, or is a socket/FIFO/device rather than a dir or regular file. Bubblewrap needs a real inode to bind.
Common situations: Evidence file replaced with a symlink to a shared store; `/var/lib/.../oracle` is a symlink; an oracle written as a fifo from a streaming producer; a path that crosses `/proc` or `/sys` symlinks.
Related errors
- read-only sandbox path must be real and non-symlink: {raw_pa
- read-only sandbox path is unavailable: {raw_path}
- extra read-only mount is unavailable: {source}
- extra read-only mount target must be absolute: {mount.target
- {label} must be a real non-symlink directory: {path}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/b38bb5df791dfde9.
Report an issue: GitHub.