mastra-ai/mastra · error · MastraError

AZURE_AD_TOKEN_ERROR

AZURE_AD_TOKEN_ERROR

Error message

Failed to get Azure AD token: ${response.status} ${error}

What it means

The gateway's OAuth client-credentials request to the Azure AD (Entra ID) token endpoint returned a non-OK HTTP response; the gateway wraps the status and response body in AZURE_AD_TOKEN_ERROR. This happens inside getAzureADToken, called by the token accessor, when Microsoft's identity platform rejects the token request.

Source

Thrown at packages/core/src/llm/model/gateways/azure.ts:391

    const body = new URLSearchParams({
      grant_type: 'client_credentials',
      client_id: clientId,
      client_secret: clientSecret,
      scope: 'https://management.azure.com/.default',
    });

    const response = await fetch(tokenEndpoint, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: body.toString(),
    });

    if (!response.ok) {
      const error = await response.text();
      throw new MastraError({
        id: 'AZURE_AD_TOKEN_ERROR',
        domain: 'LLM',
        category: 'UNKNOWN',
        text: `Failed to get Azure AD token: ${response.status} ${error}`,
      });
    }

    const tokenResponse = (await response.json()) as AzureTokenResponse;

    const expiresAt = Math.floor(Date.now() / 1000) + tokenResponse.expires_in;

    await this.tokenCache.set(cacheKey, {
      token: tokenResponse.access_token,
      expiresAt,
    });

    return tokenResponse.access_token;
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Verify tenantId, clientId, and clientSecret are correct and current (App Registration > Certificates & secrets in the Azure portal).
  2. Read the AADSTS error code in the message body — it names the exact cause (e.g. AADSTS7000215 invalid client secret).
  3. Confirm the app registration exists in the specified tenant and the secret has not expired; create a new secret if needed.
  4. Check network/proxy access to login.microsoftonline.com from the runtime environment.
  5. Ensure the requested scope (e.g. https://cognitiveservices.azure.com/.default) is granted admin consent.

Example fix

// before (stale secret)
clientSecret: process.env.AZURE_CLIENT_SECRET // old value after rotation -> 401 invalid_client
// after
clientSecret: process.env.AZURE_CLIENT_SECRET // rotated value copied fresh from Certificates & secrets, trimmed
Defensive patterns

Strategy: try-catch

Validate before calling

function assertAdCredentials(env: Record<string,string|undefined>) {
  for (const k of ['AZURE_TENANT_ID','AZURE_CLIENT_ID','AZURE_CLIENT_SECRET']) {
    if (!env[k]?.trim()) throw new Error(`${k} is not set — AD token request would fail`);
  }
}
assertAdCredentials(process.env);

Try / catch

try {
  const token = await gateway.token();
} catch (e) {
  if (e instanceof MastraError && e.id === 'AZURE_AD_TOKEN_ERROR') {
    const aadsts = /AADSTS\d+/.exec(e.message)?.[0];
    console.error(`Azure AD token request failed (${aadsts ?? 'unknown'}); check tenantId/clientId/clientSecret and network access to login.microsoftonline.com`);
    return null; // or fall back to apiKey auth
  }
  throw e;
}

Prevention

When it happens

Trigger: POST to https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token fails — e.g. 401 invalid_client (wrong clientId/secret), 400 invalid_request (bad tenantId or malformed body), 400 AADSTS700016 (app not found in tenant), or a proxy returning 403/502.

Common situations: Expired or rotated client secrets still referenced in env; client secret copied with whitespace/quotes; tenantId from a tenant where the app registration does not exist; corporate proxy blocking login.microsoftonline.com; requested scope not granted admin consent.

Related errors


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