mastra-ai/mastra · error

xAI token response missing access_token

Error message

xAI token response missing access_token

What it means

credentialsFromTokenResponse validates the xAI token endpoint response shape before constructing OAuthCredentials. If access_token is absent, empty, or not a string, the response is considered invalid and this error is thrown instead of storing broken credentials.

Source

Thrown at mastracode/sdk/src/auth/providers/xai.ts:54

/** The verification URI is opened by the user; only accept https URLs. */
function validateVerificationUri(raw: string): string {
  let parsed: URL;
  try {
    parsed = new URL(raw);
  } catch {
    throw new Error(`xAI device authorization returned an invalid verification_uri: ${raw}`);
  }
  if (parsed.protocol !== 'https:') {
    throw new Error(`xAI device authorization returned a non-https verification_uri: ${raw}`);
  }
  return parsed.toString();
}

function credentialsFromTokenResponse(data: unknown, previousRefreshToken?: string): OAuthCredentials {
  const record = (data ?? {}) as Record<string, unknown>;
  const access = record.access_token;
  if (typeof access !== 'string' || access.length === 0) {
    throw new Error('xAI token response missing access_token');
  }

  // xAI may not rotate the refresh token on refresh; keep the previous one.
  const refresh =
    typeof record.refresh_token === 'string' && record.refresh_token.length > 0
      ? record.refresh_token
      : previousRefreshToken;
  if (!refresh) {
    throw new Error('xAI token response missing refresh_token');
  }

  const expiresIn =
    typeof record.expires_in === 'number' && record.expires_in > 0
      ? record.expires_in
      : DEFAULT_TOKEN_EXPIRES_IN_SECONDS;

  return {
    access,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Log the raw response body to see what the token endpoint actually returned.
  2. For device-flow polling, ensure the user completed authorization before the request that failed (handle authorization_pending/slow_down states).
  3. Verify no proxy is altering the response and that the xAI token endpoint URL is correct.
  4. Retry the flow; if the provider contract changed, upgrade the SDK.
Defensive patterns

Strategy: type-guard

Validate before calling

// pre-check a raw token body before handing it to any consumer
function looksLikeTokenBody(b: unknown): boolean {
  const r = (b ?? {}) as Record<string, unknown>;
  return typeof r.access_token === 'string' && r.access_token.length > 0;
}

Type guard

function hasAccessToken(data: unknown): data is { access_token: string } {
  const r = (data ?? {}) as Record<string, unknown>;
  return typeof r.access_token === 'string' && r.access_token.length > 0;
}

Try / catch

try {
  await sdk.auth.login('xai', callbacks);
} catch (e) {
  if (e instanceof Error && e.message.includes('missing access_token')) {
    // response body was not a valid token grant; inspect/retry the flow
    restartDeviceFlowIfPending();
  }
}

Prevention

When it happens

Trigger: pollXAITokenOnce (during device-flow polling) or refreshXAIToken receives a JSON body where record.access_token is missing, null, or not a non-empty string.

Common situations: The token endpoint returned an error JSON (e.g. authorization_pending rendered as 200 or an error body without tokens); API contract change; proxy returning HTML that fails JSON parsing upstream or a partial body.

Related errors


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