zeroclaw-labs/zeroclaw · warning
Composio v3 tool schema lookup failed for '{slug}': {err}
Error message
Composio v3 tool schema lookup failed for '{slug}': {err} What it means
get_tool_schema fetches GET {v3}/tools/{slug}?version=latest (the slug is normalized to lowercase with hyphens) to retrieve a tool's input schema, and the call returned non-2xx — most often 404 for a name that is not a real v3 tool slug. Within Tool::execute this call is best-effort: after an execute failure it is invoked with .ok() to append an 'Expected input parameters' hint, so the error itself is swallowed there; its visible symptom is a missing schema-hint block in the execute error output.
Source
Thrown at crates/zeroclaw-tools/src/composio.rs:499
/// Fetch full metadata for a single tool by slug, including input/output parameter schemas.
/// Calls `GET /api/v3/tools/{tool_slug}` which returns the detailed schema
/// the LLM needs to construct correct `params` for `execute`.
async fn get_tool_schema(&self, tool_slug: &str) -> anyhow::Result<serde_json::Value> {
let slug = normalize_tool_slug(tool_slug);
let url = format!("{COMPOSIO_API_BASE_V3}/tools/{slug}");
ensure_https(&url)?;
let resp = self
.client()
.get(&url)
.header("x-api-key", &self.api_key)
.query(&[("version", COMPOSIO_TOOL_VERSION_LATEST)])
.send()
.await?;
if !resp.status().is_success() {
let err = response_error(resp).await;
anyhow::bail!("Composio v3 tool schema lookup failed for '{slug}': {err}");
}
let body: serde_json::Value = resp
.json()
.await
.context("Failed to decode Composio v3 tool schema response")?;
Ok(body)
}
async fn resolve_auth_config_id(&self, app_name: &str) -> anyhow::Result<String> {
let url = format!("{COMPOSIO_API_BASE_V3}/auth_configs");
let resp = self
.client()
.get(&url)
.header("x-api-key", &self.api_key)
.query(&[
("toolkit_slug", app_name),View on GitHub (pinned to 88bb9c8533)
Solutions
- If you relied on the hint, get authoritative parameters from action='list' with the app filter (its [params: ...] lines) instead.
- Pass the exact v3 slug so the schema lookup URL is valid.
- On 401 fix the API key; on 429 back off.
- Treat as non-fatal: the primary execute error and its per-candidate details are already in ToolResult.error.
Defensive patterns
Strategy: retry
Validate before calling
// Only rely on schema hints for slugs that exist in the catalog
let actions = tool.list_actions(Some(app)).await?;
let known: Vec<&str> = actions.iter().map(|a| a.name.as_str()).collect();
if !known.contains(&slug.as_str()) {
anyhow::bail!("'{slug}' is not a catalog slug; schema lookup would 404");
} Prevention
- Do not depend on the 'Expected input parameters' hint being present; use action='list'
- Use exact catalog slugs for schema lookups
- Log schema-fetch failures separately from execute failures
When it happens
Trigger: An execute failed and the fallback schema lookup used the raw action_name (a legacy alias such as GITHUB_LIST_REPOS or a free-text name) whose normalized form is not a v3 slug (404); invalid API key (401); rate limit (429); backend 5xx.
Common situations: Aliases that differ from catalog slugs; tools renamed upstream by Composio; the schema fetch hitting rate limits right after a failed execute inside tight agent loops.
Related errors
- Composio v3 API error: {err}
- Composio v3 connected accounts lookup failed: {err}
- Composio execute failed on v3 ({v3_error_summary}){prime_suf
- Composio v3 action execution failed: {err}
- Composio v3 connect failed: {err}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/05de3260863ba5f5.
Report an issue: GitHub.