{"record":{"id":"bd8796b6954025aa","repo":"Tencent/WeKnora","slug":"claim-mcp-oauth-token-refresh-w","errorCode":null,"errorMessage":"claim MCP OAuth token refresh: %w","messagePattern":"claim MCP OAuth token refresh: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/mcp/oauth_lifecycle.go","lineNumber":156,"sourceCode":"\t}\n\treturn r.refreshWithLease(ctx, row, override)\n}\n\nfunc (r *oauthRuntime) refreshWithLease(\n\tctx context.Context, observed *types.MCPOAuthToken, override *transport.OAuthHandler,\n) error {\n\tfor {\n\t\tleaseID := uuid.NewString()\n\t\tleaseDuration := r.leaseDuration\n\t\tif leaseDuration <= 0 {\n\t\t\tleaseDuration = oauthRefreshLease\n\t\t}\n\t\tleaseUntil := time.Now().Add(leaseDuration)\n\t\tacquired, err := r.repo.TryAcquireTokenRefreshLease(\n\t\t\tctx, r.tenantID, r.principal, r.serviceID, leaseID, leaseUntil,\n\t\t)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"claim MCP OAuth token refresh: %w\", err)\n\t\t}\n\t\tif acquired {\n\t\t\treturn r.refreshAsLeaseOwner(ctx, observed, leaseID, override)\n\t\t}\n\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\tcase <-time.After(oauthRefreshPoll):\n\t\t}\n\t\tcurrent, err := r.repo.GetTokenForPrincipal(ctx, r.tenantID, r.principal, r.serviceID)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"reload MCP OAuth token after concurrent refresh: %w\", err)\n\t\t}\n\t\tif current == nil || current.AccessToken == \"\" {\n\t\t\treturn &OAuthReauthorizationRequiredError{Reason: \"the refresh token is no longer valid\"}\n\t\t}\n\t\tif oauthTokenMaterialChanged(current, observed) {","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/mcp/oauth_lifecycle.go#L138-L174","documentation":"refreshWithLease attempts to become the single refresher of an OAuth token by calling repo.TryAcquireTokenRefreshLease with a unique leaseID and expiry; a repository failure here is wrapped as \"claim MCP OAuth token refresh: %w\". The lease prevents stampedes of concurrent refreshes; only the lease owner calls refreshAsLeaseOwner, others wait and re-check.","triggerScenarios":"TryAcquireTokenRefreshLease returning an error: DB unavailable, constraint/serialization failure on the lease row, or context cancellation while multiple instances race to refresh the same principal/service token.","commonSituations":"Multi-replica deployments all hitting token expiry at once and hammering the lease table; DB deadlock/timeout under load; lease table schema mismatch after migration; context deadline exceeded during the claim.","solutions":["Inspect the wrapped cause for the DB error (deadlock, timeout, duplicate key)","Retry the refresh flow with backoff — the error is often transient under contention","Verify the lease table schema/migrations are current and the lease columns are indexed","Check DB health and connection pool saturation if this recurs under load"],"exampleFix":"// before\nacquired, err := repo.TryAcquireTokenRefreshLease(ctx, ...)\nif err != nil { return err } // aborts whole refresh\n// after\nacquired, err := repo.TryAcquireTokenRefreshLease(ctx, ...)\nif err != nil {\n    if isTransient(err) { time.Sleep(backoff); return r.ensureFresh(ctx, true, override) }\n    return fmt.Errorf(\"claim MCP OAuth token refresh: %w\", err)\n}","handlingStrategy":"retry","validationCode":"if err := db.PingContext(ctx); err != nil { return fmt.Errorf(\"token store unreachable; cannot claim refresh lease: %w\", err) }","typeGuard":"func isLeaseClaimFailure(err error) bool { return err != nil && strings.Contains(err.Error(), \"claim MCP OAuth token refresh\") }","tryCatchPattern":"err := refreshWithLease(ctx, observed, override)\nif err != nil && isLeaseClaimFailure(err) {\n    // transient contention/DB hiccup: backoff and retry once\n    time.Sleep(500 * time.Millisecond)\n    return ensureFresh(ctx, true, override)\n}","preventionTips":["Use exponential backoff around refresh flows in multi-replica deployments","Keep the lease table indexed and migrations current","Set sane lease durations so expired leases clear without manual intervention","Ensure DB connection pools are sized for refresh contention spikes"],"tags":["oauth","token-refresh","lease","database","concurrency"],"backgroundTag":"token-refresh-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}