zeroclaw-labs/zeroclaw · error · anyhow::Error

Fallback provider `{raw}` resolved to `{resolved}` ({profile

Error message

Fallback provider `{raw}` resolved to `{resolved}` ({profile}) but no profile-resolved credential exists. Set `api_key` on {profile}, configure the alias's external auth flow, or remove it from `fallback`.

What it means

While assembling the reliability chain, append_fallback_chain resolves each `fallback` reference to a typed alias and calls fallback_auth_ready_for_alias. A reference that resolves but whose alias has no api_key and no configured external auth flow is a hard startup error naming the exact profile — deliberately stricter than an unresolvable reference, which is only skipped with a warning. This guarantees a declared fallback is never silently credential-less.

Source

Thrown at crates/zeroclaw-providers/src/lib.rs:1564

                WARN,
                ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)
                    .with_outcome(::zeroclaw_log::EventOutcome::Unknown)
                    .with_attrs(::serde_json::json!({"fallback": resolved})),
                "fallback ref closes a cycle; pruning"
            );
            continue;
        }

        let opts = provider_runtime_options_for_alias(config, family, &alias);
        if !factory::fallback_auth_ready_for_alias(
            config,
            family,
            &alias,
            entry.api_key.as_deref(),
            &opts,
        ) {
            let profile = format!("[providers.models.{family}.{alias}]");
            anyhow::bail!(
                "Fallback provider `{raw}` resolved to `{resolved}` ({profile}) but no \
                 profile-resolved credential exists. Set `api_key` on {profile}, configure \
                 the alias's external auth flow, or remove it from `fallback`."
            );
        }

        match create_model_provider_inner(
            Some(config),
            family,
            &alias,
            entry.api_key.as_deref(),
            entry.uri.as_deref(),
            &opts,
        ) {
            Ok(built) => push_pinned_entries(out, config, family, &alias, built, None),
            Err(e) => {
                let profile = format!("[providers.models.{family}.{alias}]");
                anyhow::bail!(

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Set `api_key` on the named profile `[providers.models.<family>.<alias>]`
  2. Complete the alias's external auth flow (e.g. `qwen login`, MiniMax token) if the family uses OAuth
  3. Remove the entry from `fallback` if it should not be a failover target
  4. Point the fallback at a different alias that is fully configured

Example fix

# before
[providers.models.openai.primary]
fallback = ["openai.backup"]

[providers.models.openai.backup]
model = "gpt-4o-mini"

# after
[providers.models.openai.primary]
fallback = ["openai.backup"]

[providers.models.openai.backup]
model = "gpt-4o-mini"
api_key = "sk-..."
Defensive patterns

Strategy: validation

Validate before calling

fn fallbacks_have_credentials(
    config: &zeroclaw_config::schema::Config,
    fallbacks: &[String],
) -> Result<(), String> {
    for raw in fallbacks {
        let Some((family, alias, entry)) = config.providers.models.find_by_name(raw) else { continue };
        let has_key = entry.api_key.as_deref().map(|k| !k.trim().is_empty()).unwrap_or(false);
        if !has_key {
            return Err(format!("fallback {family}.{alias} has no api_key or auth flow"));
        }
    }
    Ok(())
}

Try / catch

if let Err(e) = build_resilient(config, &name).await {
    if e.to_string().contains("no profile-resolved credential exists") {
        // startup config error: surface the named profile to the operator, do not retry
        return Err(e.context("configure fallback credentials or drop the fallback entry"));
    }
    return Err(e);
}

Prevention

When it happens

Trigger: `fallback = ["openai.backup"]` where `[providers.models.openai.backup]` exists but has no api_key and no resolvable env credential; an OAuth-backed alias (qwen/minimax) whose login was never performed.

Common situations: Adding fallbacks by copying alias names without copying credentials; per-provider env vars present locally but missing in CI; relying on an external auth flow that has not run on the new host.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/82a5481b0af85473. Report an issue: GitHub.