{"record":{"id":"f1a9093249716845","repo":"zeroclaw-labs/zeroclaw","slug":"composio-v3-auth-config-lookup-failed-err","errorCode":null,"errorMessage":"Composio v3 auth config lookup failed: {err}","messagePattern":"Composio v3 auth config lookup failed: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/composio.rs","lineNumber":526,"sourceCode":"\n    async fn resolve_auth_config_id(&self, app_name: &str) -> anyhow::Result<String> {\n        let url = format!(\"{COMPOSIO_API_BASE_V3}/auth_configs\");\n\n        let resp = self\n            .client()\n            .get(&url)\n            .header(\"x-api-key\", &self.api_key)\n            .query(&[\n                (\"toolkit_slug\", app_name),\n                (\"show_disabled\", \"true\"),\n                (\"limit\", \"25\"),\n            ])\n            .send()\n            .await?;\n\n        if !resp.status().is_success() {\n            let err = response_error(resp).await;\n            anyhow::bail!(\"Composio v3 auth config lookup failed: {err}\");\n        }\n\n        let body: ComposioAuthConfigsResponse = resp\n            .json()\n            .await\n            .context(\"Failed to decode Composio v3 auth configs response\")?;\n\n        if body.items.is_empty() {\n            anyhow::bail!(\n                \"No auth config found for toolkit '{app_name}'. Create one in Composio first.\"\n            );\n        }\n\n        let preferred = body\n            .items\n            .iter()\n            .find(|cfg| cfg.is_enabled())\n            .or_else(|| body.items.first())","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/composio.rs#L508-L544","documentation":"resolve_auth_config_id translates an app name into an auth config id via GET {v3}/auth_configs?toolkit_slug={app}&show_disabled=true&limit=25 before minting a connection link, and this error means that lookup returned non-2xx. Reached from action='connect' when auth_config_id is omitted; the Tool wrapper surfaces it as 'Failed to get connection URL: Composio v3 auth config lookup failed: ...'.","triggerScenarios":"connect-by-app with an invalid or revoked x-api-key (401); a toolkit_slug value the workspace cannot resolve (400/404); rate limiting (429); Composio 5xx.","commonSituations":"Wrong or rotated composio.api_key; app slug typos (normalize_app_slug fixes case and underscores, but 'githb' still fails); workspace permission issues on organization accounts.","solutions":["Check the embedded HTTP code: 401 -> fix composio.api_key and verify with action='list'.","Use the exact Composio toolkit slug for app (confirm it via action='list').","Bypass the lookup by passing auth_config_id explicitly.","On 429/5xx, back off and retry."],"exampleFix":"// before: typo'd app slug makes the auth_configs lookup fail\nlet args = json!({\"action\": \"connect\", \"app\": \"githb\"});\n\n// after: exact toolkit slug\nlet args = json!({\"action\": \"connect\", \"app\": \"github\", \"entity_id\": \"alice\"});","handlingStrategy":"retry","validationCode":"// Confirm the app exists in the catalog before connect-by-app\nlet actions = tool.list_actions(Some(app)).await?;\nif actions.is_empty() {\n    anyhow::bail!(\"unknown Composio app '{app}'; connect cannot resolve an auth config\");\n}","typeGuard":"fn is_toolkit_slug(s: &str) -> bool {\n    let t = s.trim();\n    !t.is_empty()\n        && t.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')\n}","tryCatchPattern":"match tool.execute(json!({\"action\": \"connect\", \"app\": app})).await {\n    Ok(r) if r.success => { /* open redirect_url */ }\n    Ok(r) => {\n        let e = r.error.unwrap_or_default();\n        if [\"HTTP 429\", \"HTTP 500\", \"HTTP 502\", \"HTTP 503\", \"HTTP 504\"].iter().any(|c| e.contains(c)) {\n            // retry after backoff (idempotent GET underneath)\n        }\n    }\n    Err(_) => { /* transport error */ }\n}","preventionTips":["Validate app slugs against action='list' before connect","Keep the API key current; probe with action='list' at startup","Pass auth_config_id directly when you know it, skipping the lookup"],"tags":["composio","rust","http","connect","api-key"],"backgroundTag":"api-request-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}