tinyhumansai/openhuman · error · anyhow::Error
composio client unavailable — is the user signed in? ({e})
Error message
composio client unavailable — is the user signed in? ({e}) What it means
render_integrations_agent resolves the live Composio client via the mode-aware `create_composio_client(config)` (src/openhuman/agent/debug/mod.rs:288) and wraps failure with a sign-in hint. Failure means neither the backend Composio session nor a locally-usable direct-mode credential could be constructed from current config — typically no session token / not signed in, or a malformed local Composio key.
Source
Thrown at src/openhuman/agent/debug/mod.rs:288
.map(|ci| ci.toolkit.clone())
.collect();
anyhow!(
"toolkit `{toolkit}` is not connected. Connected toolkits: [{}]",
connected.join(", ")
)
})?;
// Resolve the live client kind via the mode-aware factory so a
// direct-mode user can still render the prompt even without a
// backend session (#1710 Wave 2). Backend mode keeps the existing
// `fetch_toolkit_actions` round-trip; direct mode skips the
// refresh (no backend allowlist to consult) and keeps the cached
// catalogue, mirroring `ComposioListToolsTool`'s short-circuit.
use crate::openhuman::integrations::composio::client::{
create_composio_client, ComposioClientKind,
};
let client_kind = create_composio_client(config)
.map_err(|e| anyhow!("composio client unavailable — is the user signed in? ({e})"))?;
// Refresh the action catalogue for this toolkit at prompt-generation
// time so the dump reflects the **current** backend state rather
// than the session-start bulk fetch's snapshot (which can return an
// empty list for some toolkits even when the per-toolkit endpoint
// returns actions). Mirrors subagent_runner's typed-mode fallback:
// an empty fresh list or a network error keeps the cached catalogue
// rather than blanking it.
match &client_kind {
ComposioClientKind::Backend(composio_client) => {
match crate::openhuman::integrations::composio::fetch_toolkit_actions(
composio_client,
&integration.toolkit,
None,
)
.await
{
Ok(actions) if !actions.is_empty() => {View on GitHub (pinned to a221052e0d)
Solutions
- Sign in (the message's first suggestion) so the backend Composio client can be built.
- Or complete direct-mode Composio configuration (local API key) in Connections.
- Read the parenthesized inner `{e}` to distinguish missing-credential from malformed-config.
- Retry after authenticating; `composio list_connection` succeeding is a good pre-check that the client is constructible.
Defensive patterns
Strategy: validation
Validate before calling
// Cheap pre-check that the Composio client is constructible:
if crate::openhuman::integrations::composio::client::create_composio_client(&config).is_err() {
anyhow::bail!("sign in (or configure local Composio credentials) before dumping integrations prompts");
} Type guard
fn composio_client_ready(config: &Config) -> bool {
crate::openhuman::integrations::composio::client::create_composio_client(config).is_ok()
} Try / catch
match create_composio_client(config) {
Ok(kind) => kind,
Err(e) => {
// Do not retry: credential absence is persistent. Surface the sign-in
// hint and the inner {e}; direct users to Connections to authenticate.
return Err(anyhow!("composio client unavailable — is the user signed in? ({e})"));
}
} Prevention
- Authenticate before any integrations prompt/tool usage; `composio list_connection` succeeding is a good canary.
- For headless environments, configure direct-mode Composio credentials.
- Re-check sign-in after token-expiry events instead of assuming the session persists.
When it happens
Trigger: Prompt-dumping the integrations_agent while signed out of the backend in backend mode with no local Composio credential; config carries a partially-specified composio section (key present but invalid shape); credentials store unreadable.
Common situations: Headless/CI environments that never completed sign-in; token expired and the app hasn't refreshed; switching between backend and direct mode leaving config half-populated.
Related errors
- toolkit `{toolkit}` is not connected. Connected toolkits: [{
- integrations_agent requires a `toolkit` argument — e.g. `gma
- AgentDefinitionRegistry missing after init
- integrations_agent definition not in registry
- integrations_agent must use PromptSource::Dynamic; got {:?}
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/82a0689dbc3f2f4d.
Report an issue: GitHub.