{"record":{"id":"f60543aaa0aa0bd5","repo":"jd-opensource/joyagent-jdgenie","slug":"name-str-e","errorCode":null,"errorMessage":"调用工具 '{name}' 失败: {str(e)}","messagePattern":"调用工具 '(.+?)' 失败: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"genie-client/app/client.py","lineNumber":335,"sourceCode":"        elif not isinstance(arguments, dict):\n            raise ValueError(\"工具参数必须是字典类型\")\n\n        try:\n            async with self._sse_connection() as session:\n                logger.info(f\"正在调用工具 '{name}'，参数: {arguments}\")\n\n                # 调用工具\n                response = await session.call_tool(name=name, arguments=arguments)\n\n                logger.info(f\"工具 '{name}' 执行成功\")\n                logger.debug(f\"工具 '{name}' 返回结果类型: {type(response).__name__}\")\n\n                return response\n\n        except Exception as e:\n            error_msg = f\"调用工具 '{name}' 失败: {str(e)}\"\n            logger.error(error_msg)\n            raise Exception(error_msg) from e\n\n    def __str__(self) -> str:\n        \"\"\"返回客户端的字符串表示\"\"\"\n        return f\"SseClient(server_url='{self.server_url}', timeout={self.timeout}s)\"\n\n    def __repr__(self) -> str:\n        \"\"\"返回客户端的详细字符串表示\"\"\"\n        return (f\"SseClient(server_url='{self.server_url}', \"\n                f\"timeout={self.timeout}, \"\n                f\"sse_read_timeout={self.sse_read_timeout}, \"\n                f\"headers_count={len(self.headers)})\")\n","sourceCodeStart":317,"sourceCodeEnd":347,"githubUrl":"https://github.com/jd-opensource/joyagent-jdgenie/blob/2417e0b8b636d941ad5fb14c59b20dddfef5375d/genie-client/app/client.py#L317-L347","documentation":"`call_tool` wraps any exception raised during the SSE session or the MCP tool invocation into an Exception prefixed with the tool name. The root cause (connection failure, tool-side error, invalid arguments returned by the server) is chained via `from e`.","triggerScenarios":"`client.call_tool(name, arguments)` where the SSE connection fails, the server rejects the call, or the tool itself raises during execution.","commonSituations":"Calling a tool that doesn't exist on the server; tool argument schema mismatch; transient connectivity drop mid-call; server-side tool bug.","solutions":["Read the appended inner message / `__cause__` for the real cause","Verify the tool exists via list_tools and its input schema matches your arguments dict","Retry on transient network errors with backoff","Reproduce the call manually (curl / direct MCP session) to isolate client vs server"],"exampleFix":"// before\nawait client.call_tool(\"search\", args)\n// after\ntry:\n    await client.call_tool(\"search\", args)\nexcept Exception as e:\n    logger.exception(e.__cause__)  # unwrap the tool/server failure\n    raise","handlingStrategy":"try-catch","validationCode":"tools = {t.name for t in await client.list_tools()}\nif name not in tools:\n    raise ValueError(f\"Tool '{name}' not available on server\")","typeGuard":"async def tool_exists(client, name: str) -> bool:\n    tools = await client.list_tools()\n    return any(getattr(t, \"name\", None) == name for t in tools)","tryCatchPattern":"try:\n    return await client.call_tool(name, args)\nexcept Exception as e:\n    cause = e.__cause__\n    if isinstance(cause, (ConnectionError, TimeoutError)):\n        retry_with_backoff()\n    raise","preventionTips":["Discover tools with list_tools and validate names/arg schemas before calling","Validate arguments against the tool's input schema","Wrap calls in retry for transient network failures"],"tags":["mcp","tool-invocation"],"backgroundTag":"api-error-response","analyzedSha":"2417e0b8b636d941ad5fb14c59b20dddfef5375d","analyzedAt":"2026-09-08T11:28:19.414Z","contentChangedAt":"2026-09-08T11:28:19.414Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}