tinyhumansai/openhuman · error · anyhow::Error

[chat-factory] no model configured: role '{}' resolved to an

Error message

[chat-factory] no model configured: role '{}' resolved to an empty model id for slug '{}'. Include a model in the provider string (e.g. '{slug}:<model-id>') or set default_model on the cloud_providers entry for slug '{slug}'.

What it means

While resolving a cloud provider entry, the effective model id came back empty for a slug whose auth style needs an explicit model (factory.rs:~2185). `OpenhumanJwt` entries are exempt (the managed backend derives the model from `default_model` downstream); for everything else an empty model is fatal. The message names the role and slug and shows the `slug:<model-id>` syntax.

Source

Thrown at src/openhuman/inference/provider/factory.rs:2191

    // actionable error. Sending an empty model string to providers like
    // nvidia-nim causes a 400 "model field is required" — a confusing error
    // that obscures the real cause (missing model in the provider string or
    // unset default_model on the config entry).
    // See https://github.com/tinyhumansai/openhuman/issues/2784.
    //
    // OpenhumanJwt entries are exempt: they always delegate to
    // make_openhuman_backend which derives the model from config.default_model,
    // ignoring whatever effective_model we computed here.
    if entry.auth_style != AuthStyle::OpenhumanJwt && effective_model.trim().is_empty() {
        log::warn!(
            "[nvidia-nim][chat-factory] role={} slug={} resolved to empty model — \
             provider string must include a model id (e.g. '{}:<model-id>') or \
             set default_model on the cloud_providers entry",
            role,
            slug,
            slug,
        );
        anyhow::bail!(
            "[chat-factory] no model configured: role '{}' resolved to an empty model id for slug '{}'. \
             Include a model in the provider string (e.g. '{slug}:<model-id>') or \
             set default_model on the cloud_providers entry for slug '{slug}'.",
            role,
            slug,
        );
    }

    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,

View on GitHub (pinned to 7491200858)

Solutions

  1. Append the model id to the provider string: `my-slug:<model-id>` (e.g. `deepseek:deepseek-chat`).
  2. Or set `default_model` on the matching `cloud_providers[]` entry in config so the bare slug resolves.
  3. Verify with the role named in the message — the fix belongs on that role's provider setting.
  4. After editing config, retry; resolution runs per request.

Example fix

# config.toml — before
chat_provider = "deepseek"

# after (either form works)
chat_provider = "deepseek:deepseek-chat"
# or on the entry:
[[cloud_providers]]
slug = "deepseek"
default_model = "deepseek-chat"
Defensive patterns

Strategy: validation

Validate before calling

// Validate provider strings before they reach the factory:
fn model_id_present(provider: &str, default_model: Option<&str>) -> bool {
    provider.contains(':') || default_model.map(str::trim).is_some_and(|m| !m.is_empty())
}

Prevention

When it happens

Trigger: A provider string like `"deepseek"` with no `:<model-id>` suffix, combined with a `cloud_providers` entry for that slug that has no `default_model`, resolving to an empty effective model for the role.

Common situations: Users add a custom provider slug in Settings but never set a model; a config hand-edit sets `x_provider = "my-slug"` without the model suffix; an entry's `default_model` removed during cleanup.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/dda9bd29c332d60d. Report an issue: GitHub.