Repository navigation
fix(providers): requests for non-existent model names (deepseek-v4-pro, claude-opus-4-7) — no validation or stale catalog #2202
Description
Summary
Users are sending requests with model names that don't exist on the OpenHuman backend, resulting in 88 combined Sentry events (50 + 38) over the last 2 days. The backend rejects them with a clear 400:
Model 'deepseek-v4-pro' is not available. Use GET /openai/v1/models to list available models.
Model 'claude-opus-4-7' is not available. Use GET /openai/v1/models to list available models.
Sentry links
| Issue | Events | First seen |
|---|---|---|
OPENHUMAN-TAURI-WJ — deepseek-v4-pro |
50 | 2024-05-17 |
OPENHUMAN-TAURI-QW — claude-opus-4-7 |
38 | 2024-05-16 |
Tags observed: os=windows 10.0.26200, cpu_arch=x86_64, domain=llm_provider / domain=agent, operation=api_error / operation=native_chat, provider=OpenHuman, environment=production.
Root cause
The model name that reaches the OpenHuman backend ({api_url}/openai/v1/chat/completions) is whatever the user (or config) selected — there is no client-side validation against the backend's available model list before sending the request.
How model names flow — no validation gate
-
Config stores the model name as-is.
Config.default_model(src/openhuman/config/schema/types.rs:62) holds the user-chosen model string. Per-workload overrides (chat_provider,reasoning_provider, etc.) embed the model after a colon (e.g.openai:gpt-4o). -
Factory passes it through unchanged.
create_chat_provider_from_string()atsrc/openhuman/inference/provider/factory.rs:109parses the provider grammar (<slug>:<model>) and hands the model string to the provider constructor. For the"openhuman"path,make_openhuman_backend()(line 195) readsconfig.default_modeland falls back to"reasoning-v1"— but if the user has set a custom string like"deepseek-v4-pro", it is used verbatim. -
Provider sends to backend without checking.
OpenHumanBackendProvider(src/openhuman/inference/provider/openhuman_backend.rs) delegates toOpenAiCompatibleProviderwhich posts to/openai/v1/chat/completionswith the model field as-is. -
Backend rejects with 400. The backend's model catalog doesn't include these names, producing the errors surfaced in Sentry.
How users enter invalid model names
The AI panel (app/src/components/settings/panels/AIPanel.tsx) has a free-text input fallback for model names:
- When the
/modelsAPI fetch fails (line 1788–1810), users see "or enter model id manually:" with a bare<input>field — no validation, no autocomplete. - When the
/modelsAPI returns an empty list (line 1828–1835), the same free-text input appears. - The save handler (line 1682–1695) trims whitespace but does not validate the model name against any known catalog.
- Existing model values that the provider no longer lists are kept selectable (line 1819–1821):
{model && !cloudModels.some(m => m.id === model) && <option>}.
Both deepseek-v4-pro and claude-opus-4-7 look like plausible model names a user might type (resembling real model families but with wrong version suffixes). Neither appears in any hardcoded list in the codebase.
Proposed fix
P0 — client-side validation before request (Rust core)
In make_openhuman_backend() or as a wrapper around OpenHumanBackendProvider, validate the resolved model string against the backend's model list (GET /openai/v1/models). Cache the list with a short TTL (e.g. 5 min). If the model is not in the list:
- Log a warning with the invalid model name and the available alternatives.
- Fall back to the default model (
reasoning-v1) and surface a user-visible notification that the configured model was unavailable.
P1 — frontend validation in the AI panel
- In the free-text model input paths (lines 1804 and 1829 of
AIPanel.tsx), validate the entered model name againstcloudModelswhen the list is available. Show inline validation feedback. - When models have been fetched, disable save if the entered model is not in the list (or show a confirmation warning).
- For the "openhuman" provider specifically, pre-populate the dropdown from the backend's
/modelsendpoint rather than relying on slug-based lookup (which only works for user-added cloud providers).
P2 — stale model cleanup
- Add a config migration or startup check that validates stored model names (
default_model+ per-workload*_providermodel portions) against the backend catalog, resetting invalid entries to the default.
Affected files
src/openhuman/inference/provider/factory.rs— model resolution, no validation gatesrc/openhuman/inference/provider/openhuman_backend.rs— provider sends model as-issrc/openhuman/config/schema/types.rs—default_modelfield, no validationapp/src/components/settings/panels/AIPanel.tsx— free-text model input with no validationapp/src/services/api/aiSettingsApi.ts—listProviderModelsavailable but not used for validation
Platform
Windows 10 (build 26200), x86_64. Both issues come from the same OS version.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
fix(providers): fall back to reasoning-v1 for unrecognized default_model
fix(observability): Wave 4 classifier — socket transport + custom-pro…
fix(providers): fall back to reasoning-v1 for unrecognized default_model
fix(observability): Wave 4 classifier — socket transport + custom-pro…
fix(providers): fall back to reasoning-v1 for unrecognized default_model
fix(observability): Wave 4 classifier — socket transport + custom-pro…
fix(providers): fall back to reasoning-v1 for unrecognized default_model
fix(observability): Wave 4 classifier — socket transport + custom-pro…
fix(providers): fall back to reasoning-v1 for unrecognized default_mo…
fix(observability): Wave 4 classifier — socket transport + custom-pro…