{"record":{"id":"5c2df91bef278d0a","repo":"Kuberwastaken/claurst","slug":"rmcp-call-tool-failed","errorCode":null,"errorMessage":"rmcp call_tool '{}' failed: {}","messagePattern":"rmcp call_tool '(.+?)' failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-rust/crates/mcp/src/rmcp_backend.rs","lineNumber":525,"sourceCode":"            .await\n            .map_err(|e| anyhow::anyhow!(\"rmcp list_tools failed: {}\", e))?;\n        Ok(tools.into_iter().map(convert_tool).collect())\n    }\n\n    async fn call_tool(\n        &self,\n        name: &str,\n        arguments: Option<Value>,\n    ) -> anyhow::Result<CallToolResult> {\n        let mut params = rmcp_model::CallToolRequestParams::new(name.to_string());\n        if let Some(arguments) = arguments {\n            params = params.with_arguments(json_value_to_object(arguments)?);\n        }\n        let result = self\n            .peer\n            .call_tool(params)\n            .await\n            .map_err(|e| anyhow::anyhow!(\"rmcp call_tool '{}' failed: {}\", name, e))?;\n        Ok(convert_call_tool_result(result))\n    }\n\n    async fn list_resources(&self) -> anyhow::Result<Vec<McpResource>> {\n        let resources = self\n            .peer\n            .list_all_resources()\n            .await\n            .map_err(|e| anyhow::anyhow!(\"rmcp list_resources failed: {}\", e))?;\n        Ok(resources.into_iter().map(convert_resource).collect())\n    }\n\n    async fn read_resource(&self, uri: &str) -> anyhow::Result<ResourceContents> {\n        let result = self\n            .peer\n            .read_resource(rmcp_model::ReadResourceRequestParams::new(uri.to_string()))\n            .await\n            .map_err(|e| anyhow::anyhow!(\"rmcp read_resource '{}' failed: {}\", uri, e))?;","sourceCodeStart":507,"sourceCodeEnd":543,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/mcp/src/rmcp_backend.rs#L507-L543","documentation":"Raised in `RmcpClientBackend::call_tool` when the rmcp peer's `call_tool(params)` future fails after building a `CallToolRequestParams` for the named tool. This wraps transport failures and JSON-RPC error responses from the server's `tools/call` handler; note it does NOT cover tool-level execution errors reported inside a successful CallToolResult — only protocol-level failure of the call itself.","triggerScenarios":"Calling `call_tool(name, arguments)` where the request never completes successfully: unknown tool name (server returns 'unknown tool' JSON-RPC error), arguments fail server-side validation, session closed mid-call, transport error while sending the POST, or a timeout waiting for a long-running tool.","commonSituations":"Typo or stale tool name after the server updated its tool list; passing arguments whose types/required keys don't match the tool's input schema; tool execution exceeds the request timeout; server crashed while executing the tool.","solutions":["Call list_tools first and confirm the tool name and its input schema match the arguments being sent.","Validate arguments against the tool's JSON schema before calling (required fields, types).","Read the inner error: 'unknown tool' means the name is wrong or the server changed; 'timeout' means the tool ran too long.","Reconnect and retry if the session or transport was closed."],"exampleFix":"// before: calling with ad-hoc arguments\nbackend.call_tool(\"query_db\", Some(serde_json::json!({\"sql\": q}))).await?;\n// after: check the tool exists and arguments validate first\nlet tools = backend.list_tools().await?;\nlet tool = tools.iter().find(|t| t.name == \"query_db\")\n    .ok_or_else(|| anyhow::anyhow!(\"tool query_db not available\"))?;\nvalidate_against_schema(&tool.input_schema, &args)?;\nbackend.call_tool(\"query_db\", Some(args)).await?;","handlingStrategy":"validation","validationCode":"fn validate_tool_args(tools: &[McpTool], name: &str, args: &serde_json::Value) -> anyhow::Result<()> {\n    let tool = tools.iter().find(|t| t.name == name)\n        .ok_or_else(|| anyhow::anyhow!(\"tool '{name}' not found\"))?;\n    if let Some(obj) = args.as_object() {\n        for req in &tool.required_args {\n            anyhow::ensure!(obj.contains_key(req), \"missing required argument '{req}' for tool '{name}'\");\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match backend.call_tool(name, args).await {\n    Ok(result) => result,\n    Err(e) if e.to_string().contains(\"unknown tool\") => {\n        eprintln!(\"tool '{name}' not offered by this server; refresh tool list\");\n        default_result()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Refresh the tool list after server updates and never hardcode tool names in long-lived code.","Validate arguments against the tool's input JSON schema before calling.","Set a call timeout appropriate for the tool's expected duration.","Distinguish tool execution errors (inside a successful result) from call failures at the protocol level."],"tags":["mcp","jsonrpc","tools","rpc","arguments"],"backgroundTag":"api-request-failed","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}