Tencent/WeKnora · error

claim MCP OAuth token refresh: %w

Error message

claim MCP OAuth token refresh: %w

What it means

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.

Source

Thrown at internal/mcp/oauth_lifecycle.go:156

	}
	return r.refreshWithLease(ctx, row, override)
}

func (r *oauthRuntime) refreshWithLease(
	ctx context.Context, observed *types.MCPOAuthToken, override *transport.OAuthHandler,
) error {
	for {
		leaseID := uuid.NewString()
		leaseDuration := r.leaseDuration
		if leaseDuration <= 0 {
			leaseDuration = oauthRefreshLease
		}
		leaseUntil := time.Now().Add(leaseDuration)
		acquired, err := r.repo.TryAcquireTokenRefreshLease(
			ctx, r.tenantID, r.principal, r.serviceID, leaseID, leaseUntil,
		)
		if err != nil {
			return fmt.Errorf("claim MCP OAuth token refresh: %w", err)
		}
		if acquired {
			return r.refreshAsLeaseOwner(ctx, observed, leaseID, override)
		}

		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-time.After(oauthRefreshPoll):
		}
		current, err := r.repo.GetTokenForPrincipal(ctx, r.tenantID, r.principal, r.serviceID)
		if err != nil {
			return fmt.Errorf("reload MCP OAuth token after concurrent refresh: %w", err)
		}
		if current == nil || current.AccessToken == "" {
			return &OAuthReauthorizationRequiredError{Reason: "the refresh token is no longer valid"}
		}
		if oauthTokenMaterialChanged(current, observed) {

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Inspect the wrapped cause for the DB error (deadlock, timeout, duplicate key)
  2. Retry the refresh flow with backoff — the error is often transient under contention
  3. Verify the lease table schema/migrations are current and the lease columns are indexed
  4. Check DB health and connection pool saturation if this recurs under load

Example fix

// before
acquired, err := repo.TryAcquireTokenRefreshLease(ctx, ...)
if err != nil { return err } // aborts whole refresh
// after
acquired, err := repo.TryAcquireTokenRefreshLease(ctx, ...)
if err != nil {
    if isTransient(err) { time.Sleep(backoff); return r.ensureFresh(ctx, true, override) }
    return fmt.Errorf("claim MCP OAuth token refresh: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

if err := db.PingContext(ctx); err != nil { return fmt.Errorf("token store unreachable; cannot claim refresh lease: %w", err) }

Type guard

func isLeaseClaimFailure(err error) bool { return err != nil && strings.Contains(err.Error(), "claim MCP OAuth token refresh") }

Try / catch

err := refreshWithLease(ctx, observed, override)
if err != nil && isLeaseClaimFailure(err) {
    // transient contention/DB hiccup: backoff and retry once
    time.Sleep(500 * time.Millisecond)
    return ensureFresh(ctx, true, override)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/bd8796b6954025aa. Report an issue: GitHub.