zylon-ai/private-gpt · error · ValueError
Path '{canonical_path}' does not match any session mount.
Error message
Path '{canonical_path}' does not match any session mount. What it means
PathTranslator.to_real() maps an LLM-visible canonical path back to a real filesystem path by longest-prefix match over the session's mount table. This ValueError means the canonical_path does not start with any registered mount prefix (or the mount table is empty), so translation is impossible and — importantly for security — the path would escape the sandbox if guessed.
Source
Thrown at private_gpt/components/code_execution/path_translator.py:66
def unregister(self, canonical: str) -> None:
"""Remove a mount mapping and rebuild the internal regex."""
self._mounts = [(c, r, w) for c, r, w in self._mounts if c != canonical]
self._rebuild_regex()
# ------------------------------------------------------------------
# Path translation helpers
# ------------------------------------------------------------------
def to_real(self, canonical_path: str) -> Path:
"""Translate a canonical path to its real filesystem Path.
Raises ValueError if the path does not start with any known mount prefix.
"""
for canonical, real, _ in self._mounts:
if canonical_path.startswith(canonical):
relative = canonical_path[len(canonical) :]
return real / relative
raise ValueError(f"Path '{canonical_path}' does not match any session mount.")
def to_canonical(self, real: Path | str) -> str:
"""Reverse-translate a real path to its canonical form.
Raises ValueError if the real path is outside all mount points.
"""
real_str = str(real)
for canonical, mount_real, _ in self._mounts:
mount_str = str(mount_real)
if real_str == mount_str or real_str.startswith(mount_str + "/"):
relative = real_str[len(mount_str) :]
return canonical + relative.lstrip("/")
raise ValueError(f"Real path '{real}' is not inside any session mount.")
# ------------------------------------------------------------------
# String rewriting (commands and output)
# ------------------------------------------------------------------
View on GitHub (pinned to 4a030776a3)
Solutions
- Only pass paths previously produced by to_canonical() back into to_real()
- Register a mount covering the needed prefix via translator.register(canonical, real, writable)
- Treat the ValueError as expected LLM behavior: catch it and re-prompt the model with the list of valid mounted roots
Example fix
# before
real = translator.to_real("/etc/passwd") # not mounted
# after
try:
real = translator.to_real(canonical_path)
except ValueError:
real = None # tell the model which mounts exist Defensive patterns
Strategy: try-catch
Validate before calling
canonical_prefixes = [c for c, _, _ in translator._mounts] # or expose a public mounts property
if not any(canonical_path.startswith(c) for c in canonical_prefixes):
return error_to_model(f"path not accessible; mounted roots: {canonical_prefixes}") Type guard
def is_mounted_canonical(translator: PathTranslator, path: str) -> bool:
return any(path.startswith(c) for c, _, _ in translator._mounts) Try / catch
try:
real = translator.to_real(canonical_path)
except ValueError:
# expected when the LLM invents paths; re-prompt with valid roots
mounts = [c for c, _, _ in translator._mounts]
return f"Path is outside the sandbox. Accessible roots: {mounts}" Prevention
- Always round-trip: only feed to_real() strings produced by to_canonical()
- Include the list of mounted roots in the system prompt so the model stays inside them
- Treat unmatched paths as a normal LLM outcome (re-prompt), not an exceptional bug
When it happens
Trigger: Calling to_real() with a path invented by the LLM outside mounted roots (e.g. '/etc/passwd' when only '/home/agent/' is mounted); using a real absolute path instead of its canonical form; calling before any mounts were registered.
Common situations: Model hallucinating paths outside its sandbox; forgetting to call to_canonical() on real paths before echoing them back; mounts unregistered mid-session while old paths linger in conversation.
Related errors
- Path '{path}' is in a read-only mount ('{prefix}').
- Code execution failed: {message}
- Execution failed: {result.error or 'Unknown error'}
- Unable to view file
- Unable to replace text
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/c24343a1face7e07.
Report an issue: GitHub.