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

  1. Sign in to the app so the APP_SESSION_PROVIDER bearer token exists and `is_signed_out()` is false.
  2. Or configure a local provider: set a `subconscious` workload model (Ollama) in Connections → API keys → LLM, which routes LocalOllama and skips the auth check.
  3. Or set `subconscious_provider` to a non-cloud provider string so the route resolves to Other.
  4. 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).
  5. 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

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


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