jamiepine/voicebox · warning · HTTPException

Unknown model: {request.model_name}

Error message

Unknown model: {request.model_name}

What it means

400 from POST /models/download. The body is ModelDownloadRequest{model_name}; get_model_config(request.model_name) returns None when the id isn't in the registry, so the route raises HTTPException(400, f'Unknown model: {request.model_name}'). This is the same registry lookup used by unload/delete, so an unknown id fails identically across all three operations.

Source

Thrown at backend/routes/models.py:400

                    size_mb=None,
                    loaded=loaded,
                )
            )

    return models.ModelStatusListResponse(models=statuses)


@router.post("/models/download")
async def trigger_model_download(request: models.ModelDownloadRequest):
    """Trigger download of a specific model."""
    from ..backends import get_model_config, get_model_load_func

    task_manager = get_task_manager()
    progress_manager = get_progress_manager()

    config = get_model_config(request.model_name)
    if not config:
        raise HTTPException(status_code=400, detail=f"Unknown model: {request.model_name}")

    load_func = get_model_load_func(config)

    async def download_in_background():
        try:
            result = load_func()
            if asyncio.iscoroutine(result):
                await result
            task_manager.complete_download(request.model_name)
        except Exception as e:
            task_manager.error_download(request.model_name, str(e))

    task_manager.start_download(request.model_name)

    progress_manager.update_progress(
        model_name=request.model_name,
        current=0,
        total=0,

View on GitHub (pinned to 51f49dea19)

Solutions

  1. GET /models/status and copy the exact model_name (lowercase id like qwen3-1.7b, whisper-turbo, etc.).
  2. Send that id verbatim in the JSON body: {"model_name":"qwen3-1.7b"}.
  3. If the model isn't listed at all for your backend_type, switch backend or pick a supported equivalent.
  4. Keep the client's model list in sync with the server registry — don't hard-code ids.

Example fix

# before
curl -X POST http://localhost:8000/models/download -d '{"model_name":"Qwen3-1.7B"}'
# after
curl -X POST http://localhost:8000/models/download -d '{"model_name":"qwen3-1.7b"}'
Defensive patterns

Strategy: validation

Validate before calling

async function knownModel(name: string) {
  const status = await (await fetch('/models/status')).json();
  return status.models.some(m => m.model_name === name);
}
if (!(await knownModel(req.model_name))) {
  throw new Error(`Unknown model: ${req.model_name}`);
}
await fetch('/models/download', {method:'POST', body: JSON.stringify({model_name: req.model_name})});

Try / catch

try {
  await fetch('/models/download', {method:'POST', body: JSON.stringify({model_name})});
} catch (e) {
  if (e.response?.status === 400 && /Unknown model/.test(e.response.detail)) {
    // refresh status list, fix id, offer valid options to user
  } else throw e;
}

Prevention

When it happens

Trigger: POST /models/download {"model_name":"qwen3"} (incomplete id); {"model_name":"Qwen3-1.7B"} (wrong case); typo like 'qwen3-1.7B' or 'qwen-1.7b'; a model_name that exists in the UI but isn't registered for the current backend_type.

Common situations: Client used display_name or free text instead of the registry id; backend_type (mlx vs pytorch) doesn't expose that model; version skew between frontend model list and backend registry; user typed a repo id ('Qwen/Qwen3-1.7B') instead of the local model_name.

Related errors


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