mastra-ai/mastra · error

Failed to refresh OpenAI Codex token

Error message

Failed to refresh OpenAI Codex token

What it means

Thrown by refreshOpenAICodexToken when refreshAccessToken(refreshToken) returns a non-success result. The stored refresh token could not be exchanged for new credentials at the OpenAI token endpoint, so the library cannot silently renew the Codex credentials.

Source

Thrown at mastracode/sdk/src/auth/providers/openai-codex.ts:726

  createAuthorizationFlow,
  decodeJwt,
  extractAccountIdFromClaims,
  getAccountId,
  loginOpenAICodexDevice,
  requireAccountId,
  startLocalOAuthServer,
};

/**
 * Refresh OpenAI Codex OAuth token
 */
export async function refreshOpenAICodexToken(
  refreshToken: string,
  previousAccountId?: string,
): Promise<OAuthCredentials> {
  const result = await refreshAccessToken(refreshToken);
  if (result.type !== 'success') {
    throw new Error('Failed to refresh OpenAI Codex token');
  }

  const accountId = requireAccountId(result, previousAccountId);

  return {
    access: result.access,
    refresh: result.refresh,
    expires: result.expires,
    accountId,
  };
}

export const openaiCodexOAuthProvider: OAuthProviderInterface = {
  id: 'openai-codex',
  name: 'ChatGPT Plus/Pro (Codex Subscription)',
  usesCallbackServer: true,
  authModes: OPENAI_CODEX_AUTH_MODES,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Re-run the full Codex OAuth login to obtain fresh access and refresh tokens.
  2. Confirm the stored refresh token belongs to the current client credentials (client id/secret unchanged).
  3. Check the provider account for revoked sessions/API key resets and re-authorize.
  4. Retry once after transient network failure; if invalid_grant persists, refresh token is dead.

Example fix

// before
try {
  creds = await refreshOpenAICodexToken(storedRefresh);
} catch {}
// after
try {
  creds = await refreshOpenAICodexToken(storedRefresh);
} catch {
  creds = await loginOpenAICodex(); // full re-auth on refresh failure
}
Defensive patterns

Strategy: fallback

Validate before calling

// before refreshing: only attempt if a refresh token exists and is non-empty
if (typeof stored?.refresh !== 'string' || stored.refresh.length === 0) {
  await loginOpenAICodex(); // refresh impossible; go straight to login
}

Type guard

function hasRefreshToken(c: unknown): c is { refresh: string } {
  return typeof c === 'object' && c !== null && typeof (c as any).refresh === 'string' && (c as any).refresh.length > 0;
}

Try / catch

let creds;
try {
  creds = await refreshOpenAICodexToken(stored.refresh);
} catch {
  creds = await loginOpenAICodex(); // fall back to full re-auth
}

Prevention

When it happens

Trigger: Automatic or manual token refresh calls refreshOpenAICodexToken(refreshToken) and the provider responds with an OAuth error (invalid_grant, invalid_client, etc.), i.e. result.type !== 'success'.

Common situations: The refresh token was revoked (user logged out remotely or credentials were reset); tokens were rotated elsewhere and the stored one is stale; the OpenAI app credentials/client changed; long-unused tokens expired.

Related errors


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