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
- Set `api_key` on the named profile `[providers.models.<family>.<alias>]`
- Complete the alias's external auth flow (e.g. `qwen login`, MiniMax token) if the family uses OAuth
- Remove the entry from `fallback` if it should not be a failover target
- 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
- Add fallback entries only for aliases that already hold credentials in the same environment
- Include fallback credentials in CI secret provisioning
- Run OAuth logins for OAuth-backed fallback aliases on every host
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
- Fallback provider `{raw}` resolved to `{resolved}` ({profile
- git channel has no repositories to poll; set `repos` or gran
- start_channels requires at least one enabled [agents.<alias>
- Qdrant collection creation failed ({status}): {text}
- API key prefix mismatch: key "{visible}..." looks like a {li
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/82a5481b0af85473.
Report an issue: GitHub.