tinyhumansai/openhuman · error · anyhow::Error
No usable credentials for '{slug}', which OpenHuman selected
Error message
No usable credentials for '{slug}', which OpenHuman selected for the {} workload. Your chat model is local ('{}') and does not serve this workload, so it fell back to your cloud provider — but '{slug}' has no API key configured. Add a key for '{slug}' in Connections → LLM, set {}_provider to a provider that is configured, or enable the managed OpenHuman backend. What it means
Implicit-fallback credential failure: the user's chat model is local, so this workload (e.g. a cloud-only role) fell back to a cloud slug that has NO stored API key, and the entry's auth style is Bearer/Anthropic (styles that require a stored key — OpenhumanJwt and None are exempt). The long message (from `missing_credentials()`) explains the local-chat fallback chain and offers three remedies. Triggered at factory.rs:~2287 when `implicit_fallback && key.is_empty()`.
Source
Thrown at src/openhuman/inference/provider/factory.rs:2287
// 401 from the provider several layers later — exactly the baffling error
// this diagnostic exists to replace.
//
// Scoped to the *implicit fallback* path deliberately. That is the case the
// diagnostic is for: a local-chat user whose background role landed on a
// BYOK slug they never configured. An explicitly routed provider keeps its
// existing behaviour and is allowed to build without a stored key — callers
// construct such models to probe or describe a provider before a key is
// saved, and failing that at construction time would be a behaviour change
// well beyond this diagnostic.
//
// Styles that carry no stored key (`OpenhumanJwt` injects a session JWT
// downstream, `None` sends no auth header at all) are legitimately blank and
// never trip this.
if implicit_fallback
&& key.trim().is_empty()
&& matches!(entry.auth_style, AuthStyle::Bearer | AuthStyle::Anthropic)
{
anyhow::bail!("{}", missing_credentials());
}
let bearer_is_oauth = slug == "openai" && openai_bearer_is_oauth(config);
let codex = resolve_openai_codex_routing(config, slug, &entry.endpoint, &key, bearer_is_oauth)
.map_err(anyhow::Error::msg)?;
Ok(CloudSlugResolution {
entry,
effective_model,
key,
codex,
})
}
/// A `<slug>:<model>` BYOK cloud provider as a crate-native [`ChatModel`] — the
/// Native model for every configured cloud auth style, including the managed
/// `OpenhumanJwt` entry (issue #4727 Phase 3).
///
/// Returns `None` unless the role resolves to a **configured** cloud slug. WhenView on GitHub (pinned to 7491200858)
Solutions
- Add an API key for '{slug}' under Connections → LLM in Settings.
- Or set the `{role}_provider` for the failing workload to a provider that IS configured (or a local model that serves it).
- Or enable the managed OpenHuman backend, which needs no user key.
- Verify the slug spelling — a typo'd slug will always look key-less.
Example fix
# settings path: Connections -> LLM -> add key for the slug named in the error # or config: point the workload at a configured provider # before summary_provider = "mycustom-slug" # after summary_provider = "ollama:llama3.1:8b"
Defensive patterns
Strategy: validation
Validate before calling
// Before routing a cloud-only workload while chat is local:
let key = auth.get_provider_bearer_token(&slug, None)?.unwrap_or_default();
let needs_key = matches!(entry.auth_style, AuthStyle::Bearer | AuthStyle::Anthropic);
if key.trim().is_empty() && needs_key {
return prompt_add_key(&slug); // or pick a configured provider
} Type guard
fn slug_has_usable_key(slug: &str, entry: &CloudProviderEntry, auth: &AuthService) -> bool {
if !matches!(entry.auth_style, AuthStyle::Bearer | AuthStyle::Anthropic) { return true; }
auth.get_provider_bearer_token(slug, None)
.ok()
.flatten()
.is_some_and(|k| !k.trim().is_empty())
} Prevention
- When chat is local, review every cloud-only background role's provider and key.
- Save keys via Connections → LLM immediately after adding a slug.
- OpenhumanJwt/None auth styles need no key — misclassifying a slug's style hides this error until request time.
When it happens
Trigger: Primary chat set to a local model (Ollama etc.) while a secondary workload (title generation, embeddings, summaries) implicitly falls back to the configured cloud provider slug, whose API key was never entered in Connections → LLM.
Common situations: New users who run local chat but never added a cloud key; a key stored under a different slug name than the one configured; keys cleared by a workspace reset.
Understand the failure class
Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.
Related errors
- No usable credentials for '{slug}', which OpenHuman selected
- composio direct api key must not be empty
- OpenHuman uses the session JWT — keys are not configurable h
- OpenRouter key exchange failed (${response.status}).
- OpenRouter key exchange succeeded but no API key was returne
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/4183a16b5cdff4a4.
Report an issue: GitHub.