jamiepine/voicebox · error · ValueError

Invalid STT model '{model_size}'. Must be one of: {', '.join

Error message

Invalid STT model '{model_size}'. Must be one of: {', '.join(valid)}

What it means

Raised by _transcribe_file when the resolved model_size is not a key of WHISPER_HF_REPOS, whose keys are "base", "small", "medium", "large", and "turbo". model_size defaults to the whisper backend's current model_size if the caller did not pass model=.

Source

Thrown at backend/mcp_server/tools.py:308

        else None,
    }


# ─── Transcribe helper ─────────────────────────────────────────────────────


async def _transcribe_file(
    path: Path, language: str | None, model: str | None
) -> dict[str, Any]:
    from ..backends import WHISPER_HF_REPOS
    from ..services import transcribe as transcribe_service
    from ..utils.audio import load_audio

    whisper = transcribe_service.get_whisper_model()
    model_size = model or whisper.model_size
    valid = list(WHISPER_HF_REPOS.keys())
    if model_size not in valid:
        raise ValueError(
            f"Invalid STT model '{model_size}'. Must be one of: {', '.join(valid)}"
        )

    # load_audio is sync; keep the event loop responsive.
    audio, sr = await asyncio.to_thread(load_audio, str(path))
    duration = len(audio) / sr

    if (
        not whisper.is_loaded() or whisper.model_size != model_size
    ) and not whisper._is_model_cached(model_size):
        raise ValueError(
            f"Whisper model '{model_size}' is not yet downloaded. Open "
            "Voicebox → Settings → Models to download it first."
        )

    text = await whisper.transcribe(str(path), language, model_size)
    return {
        "text": text,

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Pass one of: "base", "small", "medium", "large", "turbo".
  2. Omit the model argument to use the loaded default.
  3. If you need a specific openai/whisper-* variant not listed, extend WHISPER_HF_REPOS rather than passing its short name.

Example fix

// before
voicebox_transcribe(audio_base64=b64, model="tiny")
// after
voicebox_transcribe(audio_base64=b64, model="base")
Defensive patterns

Strategy: validation

Validate before calling

from backend.backends import WHISPER_HF_REPOS
if model is not None and model not in WHISPER_HF_REPOS:
    raise ValueError(f"model must be one of {sorted(WHISPER_HF_REPOS)} or None")
await voicebox_transcribe(audio_base64=b64, model=model)

Type guard

def is_valid_whisper_model(value: str | None) -> bool:
    from backend.backends import WHISPER_HF_REPOS
    return value is None or (isinstance(value, str) and value in WHISPER_HF_REPOS)

Try / catch

try:
    await voicebox_transcribe(audio_base64=b64, model=model)
except ValueError as exc:
    if "Invalid STT model" in str(exc):
        await voicebox_transcribe(audio_base64=b64, model=None)  # use default
    else:
        raise

Prevention

When it happens

Trigger: Passing model="tiny"/"medium-v2"/"large-v3" directly (only the five mapped keys are accepted); passing a TTS-style size like "1.7B"; relying on a default that was misconfigured elsewhere.

Common situations: Using OpenAI whisper model names that are not in the allowlist (e.g. 'tiny', 'large-v2'); copying a size token from the TTS engines; the stored default whisper size was changed to an unsupported value.

Related errors


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