jamiepine/voicebox · error · ValueError

File not found: {audio_path}

Error message

File not found: {audio_path}

What it means

Raised by voicebox_transcribe when audio_path passes the loopback and absolute checks but Path(audio_path).is_file() is False — i.e. nothing readable exists at that path when the server checks.

Source

Thrown at backend/mcp_server/tools.py:147

        if bool(audio_base64) == bool(audio_path):
            raise ValueError(
                "Pass exactly one of `audio_base64` or `audio_path`."
            )

        # Absolute-path mode: validate and transcribe in place. Restricted
        # to loopback callers so a Voicebox bound on 0.0.0.0 doesn't double
        # as an unauthenticated arbitrary-local-file read primitive.
        if audio_path is not None:
            if not request_is_loopback():
                raise ValueError(
                    "`audio_path` is only available to loopback callers — "
                    "remote callers must use `audio_base64`."
                )
            path = Path(audio_path)
            if not path.is_absolute():
                raise ValueError("`audio_path` must be absolute.")
            if not path.is_file():
                raise ValueError(f"File not found: {audio_path}")
            if path.stat().st_size > MAX_TRANSCRIBE_BYTES:
                raise ValueError(
                    f"File exceeds {MAX_TRANSCRIBE_BYTES // (1024 * 1024)} MB limit."
                )
            return await _transcribe_file(path, language, model)

        # Base64 mode: decode into a temp file, transcribe, clean up.
        try:
            raw = b64.b64decode(audio_base64, validate=True)
        except Exception as exc:
            raise ValueError(f"Invalid audio_base64: {exc}") from exc
        if len(raw) > MAX_TRANSCRIBE_BYTES:
            raise ValueError(
                f"Audio exceeds {MAX_TRANSCRIBE_BYTES // (1024 * 1024)} MB limit."
            )
        with tempfile.NamedTemporaryFile(
            suffix=".wav", delete=False
        ) as tmp:

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Confirm the file exists from the Voicebox server's perspective (not the client's): ls -l on the host/container.
  2. Mount/share the directory into the Voicebox process if it runs in a container.
  3. Check the Voicebox process has read permission on the file.
  4. Re-verify the path is absolute and points to a regular file, not a directory or symlink.

Example fix

// before
voicebox_transcribe(audio_path="/data/clip.wav")  # missing on server
// after
# ensure /data is mounted into the Voicebox container, then
voicebox_transcribe(audio_path="/data/clip.wav")
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
p = Path(audio_path)
if not p.is_absolute() or not p.is_file():
    raise FileNotFoundError(f"audio not found or not absolute: {audio_path}")
await voicebox_transcribe(audio_path=str(p))

Type guard

def audio_path_is_readable(value: str) -> bool:
    from pathlib import Path
    p = Path(value)
    return p.is_absolute() and p.is_file() and p.stat().st_size > 0

Try / catch

try:
    await voicebox_transcribe(audio_path=audio_path)
except ValueError as exc:
    if "File not found" in str(exc):
        # verify on the server host, remount storage if needed, then retry
        raise FileNotFoundError(f"server cannot read {audio_path}; check mounts/permissions")
    raise

Prevention

When it happens

Trigger: Pointing audio_path at a path that does not exist, is a directory, lives outside an unmounted volume, or is unreadable due to permissions (the is_file check can fail on broken symlinks).

Common situations: Client and server disagree on the filesystem (container vs host paths); file was deleted between submission and check; wrong working directory used to build an 'absolute' path; permission mode hides the file from the Voicebox process.

Related errors


AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12). Data as JSON: /api/errors/9342b7ee036ffb9e. Report an issue: GitHub.