lfnovo/open-notebook · warning · HTTPException
Invalid model type. Must be one of: {valid_types}
Error message
Invalid model type. Must be one of: {valid_types} What it means
400 raised by POST /api/v1/models when model_data.type is not one of the four allowed values: language, embedding, text_to_speech, speech_to_text. The type field is validated inline in the router before any duplicate check or DB write.
Source
Thrown at api/routers/models.py:212
for model in models
]
except HTTPException:
raise
except OpenNotebookError:
raise
except Exception as e:
logger.error(f"Error fetching models: {str(e)}")
raise HTTPException(status_code=500, detail=f"Error fetching models: {str(e)}")
@router.post("/models", response_model=ModelResponse)
async def create_model(model_data: ModelCreate):
"""Create a new model configuration."""
try:
# Validate model type
valid_types = ["language", "embedding", "text_to_speech", "speech_to_text"]
if model_data.type not in valid_types:
raise HTTPException(
status_code=400,
detail=f"Invalid model type. Must be one of: {valid_types}",
)
# Check for duplicate model name under the same provider and type (case-insensitive)
from open_notebook.database.repository import repo_query
existing = await repo_query(
"SELECT * FROM model WHERE string::lowercase(provider) = $provider AND string::lowercase(name) = $name AND string::lowercase(type) = $type LIMIT 1",
{
"provider": model_data.provider.lower(),
"name": model_data.name.lower(),
"type": model_data.type.lower(),
},
)
if existing:
raise HTTPException(
status_code=400,View on GitHub (pinned to a7de90d38a)
Solutions
- Set type to exactly one of language, embedding, text_to_speech, speech_to_text (lowercase)
- Validate/normalize the type in the client before POSTing
- Update stale scripts or SDK helpers that use old type names
Example fix
// before
{"name":"gpt-4o","provider":"openai","type":"chat"}
// after
{"name":"gpt-4o","provider":"openai","type":"language"} Defensive patterns
Strategy: validation
Validate before calling
const VALID = ['language','embedding','text_to_speech','speech_to_text'];
if (!VALID.includes(model.type)) throw new Error(`type must be one of ${VALID.join(', ')}`); Type guard
const isModelType = (t: string): t is 'language'|'embedding'|'text_to_speech'|'speech_to_text' => ['language','embedding','text_to_speech','speech_to_text'].includes(t);
Try / catch
try { await api.createModel(data); } catch (e) { if (e.status === 400 && /Invalid model type/.test(e.detail)) fixType(); } Prevention
- Use a constrained dropdown/enum in forms
- Normalize to lowercase before submit
- Pin the allowed list from the API docs
When it happens
Trigger: POST /models with body type: 'chat', 'llm', 'tts', 'transcription', or any casing/typo variant; the comparison is case-sensitive so 'Language' also fails.
Common situations: Frontend sending free-text or legacy type names; scripts written against older API versions; casing mismatches.
Related errors
- {field} is required and cannot be cleared, only reassigned
- No embedding model configured. Please configure one in the M
- Item type must be either 'source' or 'note'
- Model '{model_data.name}' already exists for provider '{mode
- Invalid order_by field: '{order_by}'. Allowed fields: {', '.
AI-assisted analysis of lfnovo/open-notebook@a7de90d38a (2026-08-27).
Data as JSON: /api/errors/e5442ac781e35f7a.
Report an issue: GitHub.