vercel/ai · error · MCPClientOAuthError

OAuth authorization server metadata must be saveable before

Error message

OAuth authorization server metadata must be saveable before starting authorization

What it means

Before redirecting the user to the authorization server, the client saves the current authorization server metadata (issuer pin) via saveAuthorizationServerInformation. If the provider's storage callback reports the metadata was not actually saved, the callback phase later cannot verify the issuer, so authorization is refused before it starts.

Source

Thrown at packages/mcp/src/tool/oauth.ts:1480

    authorizationServerUrl,
    {
      metadata,
      clientInformation,
      state,
      redirectUrl: provider.redirectUrl,
      scope: selectedScope,
      resource,
    },
  );

  const savedAuthorizationServerInformation =
    await saveAuthorizationServerInformation({
      provider,
      clientInformation,
      authorizationServerInformation: currentAuthorizationServerInformation,
    });
  if (!savedAuthorizationServerInformation) {
    throw new MCPClientOAuthError({
      message:
        'OAuth authorization server metadata must be saveable before starting authorization',
    });
  }

  await provider.saveCodeVerifier(codeVerifier);
  await provider.redirectToAuthorization(authorizationUrl);
  return 'REDIRECT';
}

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Make the provider's authorization-server metadata storage actually persist (file, database, signed cookie) and return the saved value.
  2. Verify the storage backend serializes the full object (don't strip nested authorizationServerInformation fields).
  3. In serverless environments, keep the flow within one request/lambda invocation or use external durable storage for OAuth state.

Example fix

// before
saveAuthorizationServerInformation: async () => { /* no-op */ }
// after
saveAuthorizationServerInformation: async (info) => {
  await kv.set('as-metadata', info);
  return info;
}
Defensive patterns

Strategy: validation

Validate before calling

await provider.saveAuthorizationServerInformation?.(asInfo);
const readBack = await provider.getAuthorizationServerInformation?.();
if (readBack == null) {
  throw new Error('OAuth storage backend is not persisting authorization server metadata');
}

Prevention

When it happens

Trigger: Starting a new authorization (no authorizationCode): saveAuthorizationServerInformation({...}) was invoked, but the subsequent read (savedAuthorizationServerInformation) shows nothing was persisted — i.e. the provider's save/storage functions silently drop or fail to persist the authorization server metadata.

Common situations: Custom OAuth providers whose storage setter is a no-op or writes to a read-only location; storage implementations that serialize only whitelisted fields; ephemeral environments (serverless) where in-memory storage vanishes between the start and callback of the flow.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/6d95b082e8283b71. Report an issue: GitHub.