{"record":{"id":"2aeb5cdee5e93563","repo":"Tencent/WeKnora","slug":"failed-to-call-tool-w","errorCode":null,"errorMessage":"failed to call tool: %w","messagePattern":"failed to call tool: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/mcp/client.go","lineNumber":490,"sourceCode":"// CallTool calls a tool on the MCP service\nfunc (c *mcpGoClient) CallTool(ctx context.Context, name string, args map[string]interface{}) (*CallToolResult, error) {\n\tif !c.initialized {\n\t\treturn nil, ErrNotConnected\n\t}\n\n\treq := mcp.CallToolRequest{\n\t\tParams: mcp.CallToolParams{\n\t\t\tName:      name,\n\t\t\tArguments: args,\n\t\t},\n\t}\n\n\tresult, err := oauthCall(ctx, c, func() (*mcp.CallToolResult, error) {\n\t\treturn c.client.CallTool(ctx, req)\n\t})\n\tif err != nil {\n\t\tc.checkErrorAndDisconnectIfNeeded(err)\n\t\treturn nil, fmt.Errorf(\"failed to call tool: %w\", err)\n\t}\n\n\t// Convert to our types\n\tcontent := make([]ContentItem, 0, len(result.Content))\n\tfor _, item := range result.Content {\n\t\tif textContent, ok := mcp.AsTextContent(item); ok {\n\t\t\tcontent = append(content, ContentItem{\n\t\t\t\tType: \"text\",\n\t\t\t\tText: textContent.Text,\n\t\t\t})\n\t\t} else if imageContent, ok := mcp.AsImageContent(item); ok {\n\t\t\tcontent = append(content, ContentItem{\n\t\t\t\tType:     \"image\",\n\t\t\t\tData:     imageContent.Data,\n\t\t\t\tMimeType: imageContent.MIMEType,\n\t\t\t})\n\t\t}\n\t}","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/mcp/client.go#L472-L508","documentation":"CallTool wraps any failure from the underlying MCP client's CallTool RPC (including OAuth token acquisition failures handled by oauthCall) with \"failed to call tool: %w\". It first runs checkErrorAndDisconnectIfNeeded, which may mark the client disconnected if the error indicates a stale connection. The wrapped original error is preserved via %w, so errors.Is/As still work on the cause.","triggerScenarios":"Calling MCPClient.CallTool(ctx, req) when the remote MCP server is unreachable, returns a tool-execution error, the session was disconnected, or the OAuth flow inside oauthCall fails.","commonSituations":"Remote MCP server restarted or crashed (stale SSE connection); tool name typo'd so server rejects; network timeout mid-call; OAuth token refresh failed before the request was sent.","solutions":["Check the wrapped cause with errors.Is/errors.As or by inspecting err.Error() suffix to see the real failure","Verify the client is still connected; re-create the client via the manager (GetOrCreateClient) if it was disconnected by checkErrorAndDisconnectIfNeeded","Confirm the tool name and arguments match what the server advertises (GetMCPToolsInfo)","Check network connectivity and that the MCP service URL is correct"],"exampleFix":"// before\nres, err := client.CallTool(ctx, req)\nif err != nil { log.Fatal(err) }\n// after\nres, err := client.CallTool(ctx, req)\nif err != nil {\n    if errors.Is(err, ErrDisconnected) {\n        client, err = manager.GetOrCreateClient(ctx, svc) // reconnect\n    }\n    return fmt.Errorf(\"failed to call tool: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"if client == nil || !client.IsConnected() { client, err = manager.GetOrCreateClient(ctx, svc); if err != nil { return err } }","typeGuard":"func isToolCallFailure(err error) bool { return err != nil && strings.Contains(err.Error(), \"failed to call tool:\") }","tryCatchPattern":"result, err := client.CallTool(ctx, req)\nif err != nil {\n    var reauth *mcp.OAuthReauthorizationRequiredError\n    if errors.As(err, &reauth) { /* re-auth */ }\n    if isDisconnected(err) { client = reconnect(ctx, svc) }\n    return fmt.Errorf(\"tool call failed: %w\", err)\n}","preventionTips":["Reuse a manager-managed client so disconnects are detected and recreated automatically","Validate tool names against GetMCPToolsInfo before invoking","Handle the wrapped cause with errors.Is/As instead of string matching only"],"tags":["mcp","rpc","tool-invocation","wrapping"],"backgroundTag":"remote-call-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}