{"record":{"id":"f5d1f5a1d9829f2f","repo":"zed-industries/zed","slug":"error-message","errorCode":null,"errorMessage":"{error_message}","messagePattern":"\\{error_message\\}","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/agent/src/tools/context_server_registry.rs","lineNumber":398,"sourceCode":"            let request = protocol.request::<context_server::types::requests::CallTool>(\n                context_server::types::CallToolParams {\n                    name: tool_name,\n                    arguments,\n                    meta: None,\n                },\n            );\n\n            let response = futures::select! {\n                response = request.fuse() => response?,\n                _ = event_stream.cancelled_by_user().fuse() => {\n                    return Err(anyhow::anyhow!(\"MCP tool cancelled by user\").into());\n                }\n            };\n\n            if response.is_error == Some(true) {\n                let error_message: String =\n                    response.content.iter().filter_map(|c| c.text()).collect();\n                return Err(anyhow::anyhow!(error_message).into());\n            }\n\n            let mut llm_output = Vec::new();\n            let mut tool_call_content = Vec::new();\n            let mut concatenated_text = String::new();\n            for content in response.content {\n                match content {\n                    context_server::types::ToolResponseContent::Text { text } => {\n                        concatenated_text.push_str(&text);\n                        tool_call_content.push(acp::ToolCallContent::Content(acp::Content::new(\n                            acp::ContentBlock::Text(acp::TextContent::new(text.clone())),\n                        )));\n                        llm_output.push(LanguageModelToolResultContent::Text(text.into()));\n                    }\n                    context_server::types::ToolResponseContent::Image { data, mime_type } => {\n                        tool_call_content.push(acp::ToolCallContent::Content(acp::Content::new(\n                            acp::ContentBlock::Image(acp::ImageContent::new(\n                                data.clone(),","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/zed-industries/zed/blob/bc538def4545534201bbfcac4e95ac34ea6501b6/crates/agent/src/tools/context_server_registry.rs#L380-L416","documentation":"The MCP server answered the CallTool request with `is_error == Some(true)`. The error message is the concatenation of the response's text content blocks, i.e. the server's own tool-level failure relayed verbatim by Zed. The JSON-RPC transport itself succeeded; the tool execution on the server failed.","triggerScenarios":"Passing arguments the server rejects (wrong types, missing required fields); server-side failures such as missing API keys, rate limits, or absent resources the tool operates on.","commonSituations":"Schema drift between the advertised input schema and the server implementation; expired credentials for API-backed MCP tools; models hallucinating argument values.","solutions":["Read the message — it comes straight from the server and usually names the offending argument.","Validate arguments against the tool's input schema before calling.","Fix credentials or configuration on the server side, then retry.","Restart/refresh the server if its schemas changed so updated tool definitions are re-fetched."],"exampleFix":"// before\nif response.is_error == Some(true) {\n    let error_message: String = response.content.iter().filter_map(|c| c.text()).collect();\n    return Err(anyhow::anyhow!(error_message).into());\n}\n// after — keep the server context in the message\nif response.is_error == Some(true) {\n    let error_message: String = response.content.iter().filter_map(|c| c.text()).collect();\n    return Err(anyhow::anyhow!(\"MCP tool {tool_name} failed: {error_message}\").into());\n}","handlingStrategy":"try-catch","validationCode":"// Check required fields against the tool's input schema before calling:\nif let Some(required) = tool.input_schema.get(\"required\").and_then(|r| r.as_array()) {\n    for name in required {\n        let key = name.as_str().unwrap_or_default();\n        if arguments.get(key).map(|v| v.is_null()).unwrap_or(true) {\n            anyhow::bail!(\"missing required argument: {key}\");\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"if response.is_error == Some(true) {\n    let error_message: String = response.content.iter().filter_map(|c| c.text()).collect();\n    // Relay the server's text verbatim — it usually names the bad argument.\n    return Err(anyhow::anyhow!(error_message).into());\n}","preventionTips":["Validate tool arguments against the advertised input schema before dispatch.","Pass the server's error text through to the model unchanged so it can self-correct.","Keep server credentials and configuration fresh; restart servers after fixing them."],"tags":["mcp","tooling","server-error","validation"],"backgroundTag":null,"analyzedSha":"bc538def4545534201bbfcac4e95ac34ea6501b6","analyzedAt":"2026-08-16T07:30:46.435Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}