{"record":{"id":"d5647727decf4f7f","repo":"zeroclaw-labs/zeroclaw","slug":"mcp-op-server-server-name-returned-iserr","errorCode":null,"errorMessage":"MCP `{op}` (server `{server_name}`) returned isError: {detail}","messagePattern":"MCP `(.+?)` \\(server `(.+?)`\\) returned isError: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/mcp_client.rs","lineNumber":153,"sourceCode":"                .filter_map(|item| item.get(\"text\").and_then(|t| t.as_str()))\n                .collect::<Vec<_>>()\n                .join(\"\\n\")\n        })\n        .filter(|s: &String| !s.is_empty())\n        .unwrap_or_else(|| \"(no error detail returned by server)\".to_string());\n    let detail = zeroclaw_providers::sanitize_api_error(&detail);\n    ::zeroclaw_log::record!(\n        WARN,\n        ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)\n            .with_outcome(::zeroclaw_log::EventOutcome::Failure)\n            .with_attrs(::serde_json::json!({\n                \"mcp_server\": server_name,\n                \"op\": op,\n                \"detail\": &detail,\n            })),\n        \"mcp_client: MCP result returned isError:true\"\n    );\n    bail!(\"MCP `{op}` (server `{server_name}`) returned isError: {detail}\");\n}\n\n// ── Internal server state ──────────────────────────────────────────────────\n\nstruct McpServerInner {\n    config: McpServerConfig,\n    #[cfg(target_has_atomic = \"64\")]\n    next_id: AtomicU64,\n    #[cfg(not(target_has_atomic = \"64\"))]\n    next_id: AtomicU32,\n    tools: Vec<McpToolDef>,\n    capabilities: McpServerCapabilities,\n}\n\n// ── Recovery barrier ────────────────────────────────────────────────────────\n\n/// Synchronously-published gate that blocks new writes while a post-write\n/// outcome-unknown request is being recovered.","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/mcp_client.rs#L135-L171","documentation":"MCP servers report tool-execution failures as a successful JSON-RPC response whose result object carries isError: true; check_result_is_error converts that envelope into an anyhow error carrying the server-supplied detail. This is how 'the tool ran but failed' (bad arguments, missing resource, internal tool error) reaches the caller, as opposed to protocol errors.","triggerScenarios":"tools/call with arguments violating the tool's input schema; referencing a file/URI the server cannot resolve; the tool's own downstream dependency failing (API key, missing binary); server-side exceptions surfaced as error text.","commonSituations":"Schema drift after a server upgrade renames a required field; passing strings where the tool expects numbers; paths that exist on the client but not on the server host.","solutions":["Read the detail text — the server usually names the offending argument or resource","Validate arguments against the tool's inputSchema from tools/list before calling","If the server was upgraded, refresh the cached tool list; field names change between versions","Retry only when the detail clearly indicates a transient downstream failure"],"exampleFix":"// before\nlet res = server.call_tool(\"read_file\", json!({\"path\": p})).await?;\n\n// after: match the tool's declared schema first\nlet schema = tool_input_schema(&server, \"read_file\").await?;\nvalidate_args(&schema, &args)?;\nlet res = server.call_tool(\"read_file\", args).await?;","handlingStrategy":"try-catch","validationCode":"// Validate args against the tool's declared input schema before calling\nlet tools = list_tools(&server).await?;\nlet tool = tools.iter().find(|t| t.name == name).context(\"unknown tool\")?;\nvalidate_against_schema(&args, &tool.input_schema)?;\nlet result = server.call_tool(name, args).await?;","typeGuard":"fn is_tool_is_error(err: &anyhow::Error) -> bool {\n    err.to_string().contains(\"returned isError\")\n}","tryCatchPattern":"Catch, read the server-supplied detail, and branch: argument problems -> fix args and retry; missing resource -> skip or create it; transient downstream failure -> retry with backoff.","preventionTips":["Always validate arguments against the live inputSchema rather than a stale copy","Re-fetch tools/list after upgrading a server","Prefer idempotent tool usage so isError retries are safe"],"tags":["mcp","tool-call","is-error","json-rpc"],"backgroundTag":"tool-execution-error","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}