{"record":{"id":"4eb1ee3f91d46279","repo":"Tencent/WeKnora","slug":"load-mcp-oauth-token-w","errorCode":null,"errorMessage":"load MCP OAuth token: %w","messagePattern":"load MCP OAuth token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/mcp/oauth_lifecycle.go","lineNumber":119,"sourceCode":"\tif !token.ExpiresAt.IsZero() {\n\t\texpiresAt := token.ExpiresAt\n\t\tstatus.ExpiresAt = &expiresAt\n\t}\n\tif token.ExpiresAt.IsZero() || token.ExpiresAt.After(now) {\n\t\tstatus.Authorized = true\n\t\tstatus.State = oauthStateAuthorized\n\t\treturn status\n\t}\n\tif status.RefreshAvailable {\n\t\tstatus.State = oauthStateRefreshable\n\t}\n\treturn status\n}\n\nfunc (r *oauthRuntime) ensureFresh(ctx context.Context, force bool, override *transport.OAuthHandler) error {\n\trow, err := r.repo.GetTokenForPrincipal(ctx, r.tenantID, r.principal, r.serviceID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"load MCP OAuth token: %w\", err)\n\t}\n\tif row == nil || row.AccessToken == \"\" {\n\t\treturn &OAuthReauthorizationRequiredError{Reason: \"no token is stored\"}\n\t}\n\tnow := time.Now()\n\tif !force {\n\t\tif row.ExpiresAt.IsZero() || row.ExpiresAt.After(now.Add(oauthRefreshSkew)) {\n\t\t\treturn nil\n\t\t}\n\t\t// Tokens issued without refresh_token remain usable through their actual\n\t\t// expiry; the refresh skew must not shorten their lifetime.\n\t\tif row.RefreshToken == \"\" && row.ExpiresAt.After(now) {\n\t\t\treturn nil\n\t\t}\n\t}\n\tif row.RefreshToken == \"\" {\n\t\t_ = r.repo.DeleteTokenForPrincipal(ctx, r.tenantID, r.principal, r.serviceID)\n\t\treturn &OAuthReauthorizationRequiredError{Reason: \"the access token expired and no refresh token is available\"}","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/mcp/oauth_lifecycle.go#L101-L137","documentation":"oauthRuntime.ensureFresh loads the stored OAuth token row via repo.GetTokenForPrincipal; any repository failure is wrapped as \"load MCP OAuth token: %w\". A nil row or empty AccessToken is handled separately as OAuthReauthorizationRequiredError, so this error specifically means the token lookup itself failed (DB error, context cancelled, etc.).","triggerScenarios":"ensureFresh (invoked via oauthCall during any MCP call, or directly in tests) when GetTokenForPrincipal returns a database error, the context is cancelled mid-query, or the repo layer is unavailable.","commonSituations":"Database connection pool exhausted or down; migration missing so the token table doesn't exist; context cancelled because an upstream request timed out; wrong tenant/principal IDs causing a query error.","solutions":["Inspect the wrapped cause for the DB-level error (connection refused, unknown table, cancelled context)","Verify the OAuth token storage table exists and migrations are applied","Check database connectivity and pool health","If the lookup succeeds but no token exists, expect OAuthReauthorizationRequiredError instead — trigger the re-auth flow"],"exampleFix":"// before\nrow, err := repo.GetTokenForPrincipal(ctx, tenantID, principal, serviceID)\nif err != nil { return err } // opaque DB failure\n// after\nif err != nil {\n    logger.Error(\"token lookup failed\", \"err\", err)\n    return fmt.Errorf(\"load MCP OAuth token: %w\", err) // already wrapped by ensureFresh; handle upstream\n}","handlingStrategy":"try-catch","validationCode":"row, err := repo.GetTokenForPrincipal(ctx, tenantID, principal, serviceID)\nif err != nil { return fmt.Errorf(\"token store unavailable: %w\", err) }\nif row == nil || row.AccessToken == \"\" { return errors.New(\"no stored token; run OAuth flow first\") }","typeGuard":"func isTokenLoadFailure(err error) bool { return err != nil && strings.Contains(err.Error(), \"load MCP OAuth token\") }","tryCatchPattern":"err := runtime.EnsureFresh(ctx, false, nil)\nif err != nil {\n    var reauth *mcp.OAuthReauthorizationRequiredError\n    if errors.As(err, &reauth) { /* re-auth */ }\n    if isTokenLoadFailure(err) { /* check DB health / migrations */ }\n    return err\n}","preventionTips":["Apply DB migrations so the token table exists before starting workers","Monitor database connectivity; alert on token-store query failures","Ensure contexts passed into MCP calls are not already cancelled/short-deadlined"],"tags":["oauth","database","token-storage","mcp"],"backgroundTag":"token-lookup-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}