zylon-ai/private-gpt · error · ValueError
Path '{path}' is in a read-only mount ('{prefix}').
Error message
Path '{path}' is in a read-only mount ('{prefix}'). What it means
The local sandbox registers mounts as writable or read-only; _assert_writable walks the read-only prefix list and raises ValueError if a target path starts with any read-only mount prefix. It protects host-backed storage that was mounted with read-only semantics from being mutated by sandbox operations (file writes, renames, deletions).
Source
Thrown at private_gpt/components/sandbox/local.py:76
) -> None:
"""Register a new host-path mount after session creation."""
self._translator.register(canonical, host_path, writable)
if not writable and canonical not in self._readonly:
self._readonly.append(canonical)
def remove_local_mount(self, canonical: str) -> None:
"""Unregister a mount — does not delete files from host storage."""
self._translator.unregister(canonical)
self._readonly = [p for p in self._readonly if p != canonical]
async def remove_mount(self, canonical_path: str) -> None:
"""Unregister a local mount without touching host-backed storage files."""
self.remove_local_mount(canonical_path)
def _assert_writable(self, path: str) -> None:
for prefix in self._readonly:
if path.startswith(prefix):
raise ValueError(f"Path '{path}' is in a read-only mount ('{prefix}').")
async def exec(
self, command: str, opts: SandboxExecOptions | None = None
) -> SandboxExecutionResult:
cwd = self._translator.to_real(
(opts.cwd if opts else None) or self._default_cwd
)
cmd = self._translator.rewrite_command(command)
result = await self._executor.run(
cmd, cwd=cwd, timeout=opts.timeout if opts else None
)
return SandboxExecutionResult(
success=result.success,
stdout=self._translator.scrub_output(result.stdout),
stderr=self._translator.scrub_output(result.stderr),
exit_code=result.exit_code,
execution_time_ms=result.execution_time_ms,
)View on GitHub (pinned to 4a030776a3)
Solutions
- Write to a writable location (scratch/workdir mount) instead of the read-only prefix.
- If mutation is genuinely required, re-register the mount without the read-only flag (a deployment decision — read-only is usually deliberate for source data).
- Check the exact prefix strings: the check is path.startswith(prefix), so trailing slashes and case differences matter; normalize paths before comparing.
- Copy the file out of the read-only mount, modify the copy, then use it.
Example fix
# before
await sandbox.write_file("/mnt/corpus/report.txt", data) # ValueError: read-only mount
# after
await sandbox.write_file("/mnt/scratch/report.txt", data) Defensive patterns
Strategy: validation
Validate before calling
def ensure_writable(sandbox, path: str) -> bool:
try:
sandbox._assert_writable(path)
return True
except ValueError:
return False
# or track mount flags yourself
WRITABLE_ROOTS = ["/mnt/scratch"]
def writable_path(p: str) -> str:
return p if any(p.startswith(r, 0) for r in WRITABLE_ROOTS) else "/mnt/scratch/out" Try / catch
try:
await sandbox.write_file(path, data)
except ValueError as e:
if "read-only mount" in str(e):
path = "/mnt/scratch/" + Path(path).name
await sandbox.write_file(path, data)
else:
raise Prevention
- Route all agent writes to a dedicated scratch mount by convention.
- Normalize and canonicalize paths before comparing against mount prefixes.
- Surface mount read-only flags to tools/agents so they choose writable targets.
When it happens
Trigger: Any sandbox operation that calls _assert_writable(path) where path falls under a canonical prefix registered via add_local_mount(..., readonly=True) (or default read-only mounts) — e.g. writing generated files into a mounted knowledge/corpus directory.
Common situations: Agents/tools attempting to write outputs into a mounted source-data directory; mismatch between the canonical path used to register the mount and the path used at write time (prefix string comparison); forgetting that skills/corpus mounts are read-only by design.
Related errors
- Path '{canonical_path}' does not match any session mount.
- File transfer failed: {result.error}
- Invalid system specification (dict): {system}
- Invalid system item in list (dict): {item}
- 'oneOf' must be an array of schemas
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/daea5b1c5ae1dc8f.
Report an issue: GitHub.