tinyhumansai/openhuman · error · anyhow::Error
provider unavailable: {reason}
Error message
provider unavailable: {reason} What it means
The subconscious CLI pre-flight check calls `subconscious_provider_unavailable_reason(&config)` (src/openhuman/subconscious/provider.rs:37) and hard-fails with the reason when Some. In practice the reason is one of: "Sign in to use the OpenHuman cloud Subconscious provider." (scheduler gate says signed out), "Sign in or configure a local Subconscious provider..." (AuthService found no non-empty bearer for APP_SESSION_PROVIDER), or "Unable to read the OpenHuman session: {e}" (keyring/credential store error). It only fires when the resolved route is OpenHumanCloud — LocalOllama and Other provider routes always pass.
Source
Thrown at src/core/subconscious_cli.rs:141
eprintln!("[subconscious] session token found — provider available");
}
Ok(None) => {
eprintln!("[subconscious] WARNING: no session token — cloud provider will fail");
eprintln!(" hint: run `openhuman call auth store_session --token <JWT>` first");
}
Err(e) => {
eprintln!("[subconscious] WARNING: session token read failed: {e}");
}
}
// Check provider availability
if let Some(reason) =
crate::openhuman::subconscious::provider::subconscious_provider_unavailable_reason(
&config,
)
{
eprintln!("[subconscious] provider unavailable: {reason}");
return Err(anyhow!("provider unavailable: {reason}"));
}
// Create engine and run tick. The engine pulls its own memory_diff /
// context state from the workspace — no memory client to pass in.
let engine = crate::openhuman::subconscious::memory_instance(&config);
eprintln!("[subconscious] running tick...");
let result = engine
.tick()
.await
.map_err(|e| anyhow!("tick failed: {e}"))?;
eprintln!(
"[subconscious] tick complete: duration={}ms response_chars={}",
result.duration_ms, result.response_chars,
);
if flags.verbose {View on GitHub (pinned to a221052e0d)
Solutions
- Sign in to the app so the APP_SESSION_PROVIDER bearer token exists and `is_signed_out()` is false.
- Or configure a local provider: set a `subconscious` workload model (Ollama) in Connections → API keys → LLM, which routes LocalOllama and skips the auth check.
- Or set `subconscious_provider` to a non-cloud provider string so the route resolves to Other.
- If the reason says 'Unable to read the OpenHuman session', fix the credential store permissions/path (state dir is config_path's parent, falling back to workspace_dir).
- Verify first with `openhuman subconscious status` — it prints the same provider_reason only when the mode is enabled.
Example fix
# before openhuman subconscious tick # signed out, cloud route -> provider unavailable # after: sign in via the app, or pin a local model in config.toml [workload_models] subconscious = "ollama://localhost:11434/llama3.1"
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight the same check the CLI makes (provider.rs): run // `openhuman subconscious status` first and require a healthy provider // before ticking: // openhuman subconscious status # prints provider state when mode enabled // In-process callers can call // subconscious_provider_unavailable_reason(&config) // (pub(crate) — exposed via SubconsciousStatus.provider_unavailable_reason over RPC) // and abort before engine construction when it returns Some.
Try / catch
match run_tick().await {
Err(e) if e.to_string().starts_with("provider unavailable") => {
// Re-run `status` to fetch the actionable reason and surface it;
// do not retry until sign-in or a local model is configured.
}
other => other,
} Prevention
- Run `subconscious status` before tick in scripts and gate on healthy output.
- Configure a local subconscious workload model for headless/CI so the cloud sign-in requirement disappears.
- Keep the app signed in; watch for scheduler-gate sign-out after token expiry.
When it happens
Trigger: `openhuman subconscious tick` (or the run path at src/core/subconscious_cli.rs:141) while `subconscious_provider` is unset/"cloud"/"openhuman" AND the user is signed out, has an empty/missing session token in the state dir next to config_path, or the credential store is unreadable. A local `subconscious` workload model in config bypasses the check entirely.
Common situations: Fresh install where the user never signed in; session token expired and cleared; state dir moved so AuthService::new points at a directory with no stored session; running the tick headless in CI/docker where no sign-in ever happened.
Related errors
- unknown mode '{other}', expected simple|aggressive
- Invalid ${paramName}: must be an array of IDs.
- Invalid ${paramName}[${index}]: ${errorMsg}
- PAYMENT_REQUIRED
- Sentry.flush(2000) timed out — event may not have reached Se
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/e341b28ea1daa914.
Report an issue: GitHub.