tinyhumansai/openhuman · error · anyhow::Error
[chat-factory] model '{}' is an abstract tier for role '{}',
Error message
[chat-factory] model '{}' is an abstract tier for role '{}', but cloud provider slug '{}' has no concrete default_model configured. Set cloud_providers[].default_model to a provider-native model id (e.g. deepseek-v4-pro). What it means
The effective model for a role resolved to an abstract tier name (something `is_abstract_tier_model` recognizes, e.g. a tier like 'fast'/'balanced' rather than a provider-native model id). The factory tried to remap it to a concrete model via the entry's `default_model`, but that field is missing or itself abstract/blank, so it bails (factory.rs:~2205-2216).
Source
Thrown at src/openhuman/inference/provider/factory.rs:2216
}
if entry.auth_style != AuthStyle::OpenhumanJwt && is_abstract_tier_model(&effective_model) {
if let Some(default_model) = entry
.default_model
.as_deref()
.map(str::trim)
.filter(|m| !m.is_empty() && !is_abstract_tier_model(m))
{
log::info!(
"[providers][chat-factory] role={} slug={} remapping abstract model {} -> {}",
role,
slug,
effective_model,
default_model
);
effective_model = default_model.to_string();
} else {
anyhow::bail!(
"[chat-factory] model '{}' is an abstract tier for role '{}', \
but cloud provider slug '{}' has no concrete default_model configured. \
Set cloud_providers[].default_model to a provider-native model id (e.g. deepseek-v4-pro).",
effective_model,
role,
slug
);
}
}
log::info!(
"[providers][chat-factory] role={} slug={} model={} endpoint_host={}",
role,
slug,
effective_model,
redact_endpoint(&entry.endpoint)
);
View on GitHub (pinned to 7491200858)
Solutions
- Set `cloud_providers[].default_model` to a provider-native model id, e.g. `deepseek-v4-pro`.
- Or bypass the tier entirely: put a concrete model in the provider string (`slug:<concrete-model>`).
- Check the entry with the slug named in the message — the fix is scoped to that entry.
- Retry the request after saving config.
Example fix
# config.toml — before [[cloud_providers]] slug = "deepseek" default_model = "fast" # after [[cloud_providers]] slug = "deepseek" default_model = "deepseek-v4-pro"
Defensive patterns
Strategy: validation
Validate before calling
fn concrete_model_configured(entry: &CloudProviderEntry, effective_model: &str) -> bool {
if !is_abstract_tier_model(effective_model) { return true; }
entry.default_model.as_deref()
.map(|m| !m.trim().is_empty() && !is_abstract_tier_model(m))
.unwrap_or(false)
} Prevention
- Never copy tier names ('fast', 'quality') into BYOK entries — use provider-native model ids.
- When a settings UI offers tiers for custom slugs, map them to concrete defaults on save.
- Lint `default_model` values to reject abstract tier strings.
When it happens
Trigger: A role configured with an abstract tier model (e.g. `fast`, `quality`) on a custom `cloud_providers` slug whose entry lacks a concrete `default_model`, or whose `default_model` is another abstract tier rather than a real model id like `deepseek-v4-pro`.
Common situations: Copying a provider config from the managed backend (where tiers are valid) to a BYOK slug (where they are not); setting `default_model = "fast"` by mistake; deleting the `default_model` line while editing an entry.
Related errors
- [chat-factory] no model configured: role '{}' resolved to an
- OPENAI_CODEX_OAUTH_MISSING_AUTH_URL
- Core returned an empty backend URL
- encryption key must decode to 32 raw bytes (raw, base64, or
- memory driver `{driver_id}` does not advertise the `{cap}` c
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/4759a881e6d218aa.
Report an issue: GitHub.