{"record":{"id":"4a57a32fcc06c53c","repo":"Tencent/WeKnora","slug":"failed-to-read-resource-w","errorCode":null,"errorMessage":"failed to read resource: %w","messagePattern":"failed to read resource: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/mcp/client.go","lineNumber":533,"sourceCode":"\n// ReadResource reads a resource from the MCP service\nfunc (c *mcpGoClient) ReadResource(ctx context.Context, uri string) (*ReadResourceResult, error) {\n\tif !c.initialized {\n\t\treturn nil, ErrNotConnected\n\t}\n\n\treq := mcp.ReadResourceRequest{\n\t\tParams: mcp.ReadResourceParams{\n\t\t\tURI: uri,\n\t\t},\n\t}\n\n\tresult, err := oauthCall(ctx, c, func() (*mcp.ReadResourceResult, error) {\n\t\treturn c.client.ReadResource(ctx, req)\n\t})\n\tif err != nil {\n\t\tc.checkErrorAndDisconnectIfNeeded(err)\n\t\treturn nil, fmt.Errorf(\"failed to read resource: %w\", err)\n\t}\n\n\t// Convert to our types\n\tcontents := make([]ResourceContent, 0, len(result.Contents))\n\tfor _, item := range result.Contents {\n\t\tif textContent, ok := mcp.AsTextResourceContents(item); ok {\n\t\t\tcontents = append(contents, ResourceContent{\n\t\t\t\tURI:      textContent.URI,\n\t\t\t\tMimeType: textContent.MIMEType,\n\t\t\t\tText:     textContent.Text,\n\t\t\t})\n\t\t} else if blobContent, ok := mcp.AsBlobResourceContents(item); ok {\n\t\t\tcontents = append(contents, ResourceContent{\n\t\t\t\tURI:      blobContent.URI,\n\t\t\t\tMimeType: blobContent.MIMEType,\n\t\t\t\tBlob:     blobContent.Blob,\n\t\t\t})\n\t\t}","sourceCodeStart":515,"sourceCodeEnd":551,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/mcp/client.go#L515-L551","documentation":"ReadResource wraps any failure from the underlying MCP client's ReadResource RPC (including OAuth failures from oauthCall) with \"failed to read resource: %w\". checkErrorAndDisconnectIfNeeded is invoked first and may flag the connection as broken. The original error is preserved for errors.Is/As unwrapping.","triggerScenarios":"Calling MCPClient.ReadResource(ctx, req) when the server is unreachable, the resource URI does not exist or is rejected, the session died, or OAuth token handling inside oauthCall failed.","commonSituations":"Requesting a resource URI the server doesn't expose; server restarted so the SSE session is stale; permission denied server-side; token expired and refresh failed.","solutions":["Inspect the wrapped cause (errors.Unwrap / %w suffix) for the real server or network error","Verify the resource URI against the server's advertised resources list","Reconnect: recreate the client via GetOrCreateClient if checkErrorAndDisconnectIfNeeded marked it disconnected","Check OAuth token state for the principal/service; re-authorize if refresh failed"],"exampleFix":"// before\nc, err := client.ReadResource(ctx, req)\nif err != nil { panic(err) }\n// after\nc, err := client.ReadResource(ctx, req)\nif err != nil {\n    var reauth *OAuthReauthorizationRequiredError\n    if errors.As(err, &reauth) { /* trigger re-auth flow */ }\n    return nil, fmt.Errorf(\"failed to read resource: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"resources, err := client.ListResources(ctx)\nif err != nil { return err }\nif !uriInList(req.URI, resources) { return fmt.Errorf(\"resource %s not offered by service\", req.URI) }","typeGuard":"func isResourceReadFailure(err error) bool { return err != nil && strings.Contains(err.Error(), \"failed to read resource:\") }","tryCatchPattern":"contents, err := client.ReadResource(ctx, req)\nif err != nil {\n    var reauth *mcp.OAuthReauthorizationRequiredError\n    if errors.As(err, &reauth) { /* trigger re-auth */ }\n    return fmt.Errorf(\"resource read failed: %w\", err)\n}","preventionTips":["List the server's resources first and validate the URI exists before reading","Re-create stale clients after server restarts","Keep OAuth tokens fresh; watch for OAuthReauthorizationRequiredError in the wrapped chain"],"tags":["mcp","rpc","resource-read","wrapping"],"backgroundTag":"remote-call-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}