jamiepine/voicebox · warning · HTTPException
Unknown model: {model_name}
Error message
Unknown model: {model_name} What it means
400 from POST /models/{model_name}/unload. get_model_config(model_name) walks the full registry (Qwen TTS + custom voice + non-Qwen TTS + Whisper + Qwen LLM) and returns None when no config.model_name matches. The route then raises HTTPException(400, f'Unknown model: {model_name}'). model_name comes from the path, so typos and case mismatches are the usual cause.
Source
Thrown at backend/routes/models.py:82
async def unload_model():
"""Unload the default Qwen TTS model to free memory."""
from ..services import tts
try:
tts.unload_tts_model()
return {"message": "Model unloaded successfully"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/models/{model_name}/unload")
async def unload_model_by_name(model_name: str):
"""Unload a specific model from memory without deleting it from disk."""
from ..backends import get_model_config, unload_model_by_config
config = get_model_config(model_name)
if not config:
raise HTTPException(status_code=400, detail=f"Unknown model: {model_name}")
try:
was_loaded = unload_model_by_config(config)
if not was_loaded:
return {"message": f"Model {model_name} is not loaded"}
return {"message": f"Model {model_name} unloaded successfully"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/models/progress/{model_name}")
async def get_model_progress(model_name: str):
"""Get model download progress via Server-Sent Events."""
progress_manager = get_progress_manager()
async def event_generator():
async for event in progress_manager.subscribe(model_name):
yield eventView on GitHub (pinned to 51f49dea19)
Solutions
- Use the exact lowercase registry id, e.g. qwen3-1.7b, qwen3-0.6b, qwen3-4b, or the Whisper/TTS ids.
- GET /models/status to list valid model_name values; copy the id verbatim into the path.
- Trim whitespace and avoid URL-encoding the hyphen.
- If maintaining the client, derive the id from the same registry source the server uses, not from display_name.
Example fix
# before curl -X POST http://localhost:8000/models/Qwen3-1.7B/unload # after curl -X POST http://localhost:8000/models/qwen3-1.7b/unload
Defensive patterns
Strategy: validation
Validate before calling
async function validModelName(name: string) {
const status = await (await fetch('/models/status')).json();
return status.models.some(m => m.model_name === name);
}
if (!(await validModelName(modelName))) {
throw new Error(`Unknown model: ${modelName}. Check /models/status for valid ids.`);
} Try / catch
try {
await fetch(`/models/${encodeURIComponent(modelName)}/unload`, {method:'POST'});
} catch (e) {
if (e.response?.status === 400 && /Unknown model/.test(e.response.detail)) {
// refresh model list, fix the id, retry
} else throw e;
} Prevention
- Always copy model_name verbatim from GET /models/status (lowercase ids, hyphen-separated).
- Never build the URL from display_name or repo_id.
- Keep the client's model list sourced from the live registry.
When it happens
Trigger: POST /models/qwen3/unload (no such model_name); /models/Qwen3-1.7B/unload (wrong case — registry ids are lowercase like 'qwen3-1.7b'); /models/kokoro/unload when kokoro is registered under a different id; trailing slash or whitespace in the path segment.
Common situations: User typed a display name ('Qwen3 1.7B') instead of the id; client built the URL from a display_name field; registry was extended but client uses an outdated id; confusion between TTS model_name and LLM model_name.
Related errors
- Unknown model: {request.model_name}
- Source and destination are the same directory
- Destination cannot be inside the current cache directory
- Model ${model_size} is not downloaded yet. Use /generate to
- Model {model_size} is not downloaded yet. Use /generate to t
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/981460d46c7104ea.
Report an issue: GitHub.