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

  1. Only pass paths previously produced by to_canonical() back into to_real()
  2. Register a mount covering the needed prefix via translator.register(canonical, real, writable)
  3. 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

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


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/c24343a1face7e07. Report an issue: GitHub.