tinyhumansai/openhuman · error · anyhow::Error

Composio v2 connect failed: {err}

Error message

Composio v2 connect failed: {err}

What it means

Non-2xx from the legacy v2 POST connect fallback (get_connection_url_v2). Reached only when v3 connect already failed and an app name was available. response_error folds status + body into {err}; on success a redirect URL is extracted, so a missing redirect is a separate error.

Source

Thrown at src/openhuman/integrations/composio/tools/direct.rs:603

    ) -> anyhow::Result<String> {
        let url = format!("{}/connectedAccounts", self.base_v2);

        let body = json!({
            "integrationId": app_name,
            "entityId": entity_id,
        });

        let resp = self
            .client()
            .post(&url)
            .header("x-api-key", &self.api_key)
            .json(&body)
            .send()
            .await?;

        if !resp.status().is_success() {
            let err = response_error(resp).await;
            anyhow::bail!("Composio v2 connect failed: {err}");
        }

        let result: serde_json::Value = resp
            .json()
            .await
            .context("Failed to decode Composio v2 connect response")?;
        extract_redirect_url(&result)
            .ok_or_else(|| anyhow::anyhow!("No redirect URL in Composio v2 response"))
    }

    /// List the user's connected accounts on Composio v3.
    ///
    /// GET `https://backend.composio.dev/api/v3/connected_accounts` with
    /// `x-api-key: <user_key>`. Returns the raw item list; reshaping
    /// into [`super::super::super::composio::types::ComposioConnection`]
    /// happens at the call site in `composio/client.rs::direct_list_connections`.
    ///
    /// The v3 envelope is `{ items: [{ id, status, toolkit, created_at, ... }] }`.

View on GitHub (pinned to 7491200858)

Solutions

  1. Diagnose the v3 error first — v2 failing with a similar 4xx usually confirms the app/slug problem
  2. Use Composio's canonical app key for v2 if you must target it
  3. 401: fix the API key; 429/5xx: retry with backoff
Defensive patterns

Strategy: try-catch

Try / catch

match tool.get_connection_url(app, None, &entity).await {
    Ok(url) => ui.open(url),
    Err(e) => {
        // v3 already failed and v2 (appName route) failed too — report the pair verbatim
        tracing::warn!("[composio] connect failed both APIs: {e:#}");
        ui.show_connect_error(&format!("{e:#}"));
    }
}

Prevention

When it happens

Trigger: Unknown appName in the v2 registry (404/400); app enabled only in v3; 401; 429/5xx. Typically the second half of the combined connect failure message.

Common situations: Newer toolkits absent from the v2 catalogue; appName passed with wrong casing or a display name; auth/network problems hitting both versions.

Related errors


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