mastra-ai/mastra · error · Error
No OAuth authorization is pending for this server. Call conn
Error message
No OAuth authorization is pending for this server. Call connect() first.
What it means
finishAuth(authorizationCode) completes a pending OAuth token exchange started when connect() hit a 401 and deferred to an authorization flow. If no such pending authorization exists (pendingAuthTransport is undefined), this error is thrown because there is no transport waiting for the authorization code.
Source
Thrown at packages/mcp/src/client/client.ts:791
get authState(): MCPServerAuthState | undefined {
return this._authState;
}
/**
* Completes a pending OAuth authorization-code flow.
*
* Exchanges the authorization code captured at the redirect URI on the same
* transport that started the flow, then leaves the client ready to connect().
*
* @param authorizationCode - The authorization code captured at the redirect URI
* @throws {Error} If no authorization flow is pending for this server
*
* @internal
*/
async finishAuth(authorizationCode: string): Promise<void> {
const pending = this.pendingAuthTransport;
if (!pending) {
throw new Error('No OAuth authorization is pending for this server. Call connect() first.');
}
this.pendingAuthTransport = undefined;
try {
await pending.finishAuth(authorizationCode);
} finally {
// The pending transport only ran the token exchange; the next connect() builds a fresh one.
void pending.close().catch(() => {});
}
}
private isConnected: Promise<boolean> | null = null;
private reconnectPromise: Promise<void> | null = null;
private lifecycleGeneration = 0;
/**
* Connects to the MCP server using the configured transport.
*
* Automatically detects transport type based on configuration (stdio vs HTTP).View on GitHub (pinned to 75dd419e61)
Solutions
- Only call finishAuth after connect() rejected with an authorization requirement
- Track whether an OAuth flow is in progress; gate the callback on that flag
- Make the OAuth callback idempotent (ignore repeat calls)
- If state was lost, call connect() again to restart the authorization flow
Example fix
// before
await client.finishAuth(req.query.code); // throws when nothing pending
// after
try {
await client.finishAuth(req.query.code);
} catch (e) {
if (!(e instanceof Error) || !e.message.includes('No OAuth authorization is pending')) throw e;
await client.connect(); // restart or ignore duplicate callback
} Defensive patterns
Strategy: try-catch
Validate before calling
// only call finishAuth when connect() surfaced an authorization requirement
let authPending = false;
try { await client.connect(); } catch { authPending = true; }
if (authPending) await client.finishAuth(code); Try / catch
try {
await client.finishAuth(code);
} catch (e) {
if (e instanceof Error && e.message.includes('No OAuth authorization is pending')) {
// duplicate callback or no flow in progress: ignore or restart connect()
return;
}
throw e;
} Prevention
- Gate the OAuth callback handler on a 'flow in progress' flag
- Make the callback idempotent against repeated redirects
- Only call finishAuth after a 401-driven connect() failure
- Restart with connect() to re-establish pending state if lost
When it happens
Trigger: Calling client.finishAuth(code) without a preceding connect() that triggered the OAuth flow; calling finishAuth twice; calling it after connect() already completed the exchange; calling it after a disconnect cleared the pending transport.
Common situations: OAuth callback invoked more than once (double browser redirect); application flow calls finishAuth unconditionally instead of only after a 401-driven redirect; server credentials already valid so connect() never triggered OAuth.
Related errors
- No code verifier found. Authorization flow may not have star
- Bearer token required
- State token has expired
- Redirect URI is required for SSO login
- Token exchange failed: ${error}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/73d68529acb28876.
Report an issue: GitHub.