mastra-ai/mastra · info · Error

Authentication for MCP server

Error message

Authentication for MCP server ${serverName} was cancelled.

What it means

Plain Error thrown by the throwIfAborted checkpoint inside runAuthorizationFlow. When an OAuth authorization flow is started for a server, an AbortController is stored; if cancelAuth (or disconnect) aborts it, subsequent checkpoints throw this message to unwind the flow instead of leaving it waiting on the callback code.

Solutions

  1. Treat this as an expected cancellation: catch it and skip/retry the auth flow rather than treating it as a fault.
  2. If unintentional, audit code paths that call cancelAuth/disconnect for the server during setup.
  3. Restart the authentication flow (call the authenticate/flow method again) once cancellation is no longer desired.
  4. Check for duplicate/overlapping auth flows for the same serverName that may abort each other.

Example fix

// before
await client.authenticateServer('github'); // may throw on cancel
// after
try {
  await client.authenticateServer('github');
} catch (e) {
  if ((e as Error).message.includes('was cancelled')) return; // expected cancel
  throw e;
}
Defensive patterns

Strategy: try-catch

Type guard

function isAuthCancelled(e: unknown): boolean {
  return e instanceof Error && e.message.includes('was cancelled');
}

Try / catch

try {
  await client.authenticateServer(serverName);
} catch (e) {
  if (isAuthCancelled(e)) return; // user/system cancelled: expected
  throw e;
}

Prevention

When it happens

Trigger: Calling client.cancelAuthentication(serverName) or disconnecting the server while runAuthorizationFlow is mid-flight (during discovery, registration, port binding, or while waiting for the OAuth callback code).

Common situations: User cancels a browser-based login; application shuts down or times out an auth attempt; a re-authentication request supersedes an in-progress flow for the same server.

Understand the failure class

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/b4d35c2ac17fa3a2. Report an issue: GitHub.

Appendix: source

Thrown at packages/mcp/src/client/configuration.ts:874

  /**
   * OAuth authorization state of a configured server.
   *
   * Returns `undefined` for servers without an authProvider and for servers
   * that have not attempted a connection yet.
   */
  public getServerAuthState(serverName: string): MCPServerAuthState | undefined {
    return this.mcpClientsById.get(serverName)?.authState;
  }

  private async runAuthorizationFlow(serverName: string, options?: { timeoutMs?: number }): Promise<void> {
    // Register the abort controller synchronously, before the first await, so a
    // cancel/disconnect during the setup phase (discovery, registration, port
    // binding) can interrupt the flow rather than letting it park on waitForCode.
    const abortController = new AbortController();
    this.authAbortControllersByServer.set(serverName, abortController);
    const throwIfAborted = () => {
      if (abortController.signal.aborted) {
        throw new Error(`Authentication for MCP server ${serverName} was cancelled.`);
      }
    };

    // Resources acquired during setup that must be released on every exit path.
    // Tracked here so the single outer finally can tear them down even if a
    // fallible setup step (session begin, port binding) throws.
    let provider: MCPOAuthClientProvider | undefined;
    let sessionStarted = false;
    let callbackServer: OAuthCallbackServer | undefined;

    // Installed before the first fallible step so the abort-controller entry,
    // provider session, and callback server never leak on an early throw.
    try {
      const config = this.getServerConfig(serverName);
      const candidateProvider = config.authProvider;
      if (!(candidateProvider instanceof MCPOAuthClientProvider)) {
        throw new Error(
          `Cannot authenticate MCP server ${serverName}: it is not configured with an MCPOAuthClientProvider.`,

View on GitHub (pinned to 75dd419e61)