mastra-ai/mastra · error
GitHub OAuth token exchange failed: ${res.status}
Error message
GitHub OAuth token exchange failed: ${res.status} What it means
The GitHub OAuth web-application flow token exchange (POST to https://github.com/login/oauth/access_token with client_id, client_secret, code, redirect_uri) returned a non-OK HTTP status; the integration surfaces the status code in this error.
Source
Thrown at mastracode/factory/src/integrations/github/integration.ts:1123
url.searchParams.set('state', state);
return url.toString();
}
/** Exchange an OAuth `code` for a user access token. */
async exchangeOAuthCode(code: string, redirectUri: string): Promise<string> {
const res = await fetch('https://github.com/login/oauth/access_token', {
method: 'POST',
signal: AbortSignal.timeout(GITHUB_OAUTH_TOKEN_TIMEOUT_MS),
headers: { 'content-type': 'application/json', accept: 'application/json' },
body: JSON.stringify({
client_id: this.#clientId,
client_secret: this.#clientSecret,
code,
redirect_uri: redirectUri,
}),
});
if (!res.ok) {
throw new Error(`GitHub OAuth token exchange failed: ${res.status}`);
}
const data = (await res.json()) as { access_token?: string; error?: string; error_description?: string };
if (!data.access_token) {
throw new Error(
`GitHub OAuth token exchange returned no token: ${data.error_description ?? data.error ?? 'unknown'}`,
);
}
return data.access_token;
}
/**
* The integration's HTTP surface: the `/web/github/*` + `/auth/github/*`
* Mastra `apiRoutes` (webhook handler, install/OAuth flow, project +
* worktree + session operations). The factory folds these into the server's
* `apiRoutes` when the feature is ready. Handlers operate on this instance.
*/
routes(ctx: IntegrationContext): ApiRoute[] {
this.#storage = ctx.storage;View on GitHub (pinned to 75dd419e61)
Solutions
- Verify clientId and clientSecret match the GitHub OAuth App
- Ensure redirect_uri is byte-identical to the one used in the authorize redirect and registered on the app
- Re-run the OAuth flow to obtain a fresh authorization code (codes are single-use and short-lived)
- Retry the flow after checking the GitHub status page if the status is 5xx
Example fix
// before redirect_uri: 'https://app.example.com/auth/github/callback/' // trailing slash differs from authorize step // after redirect_uri: 'https://app.example.com/auth/github/callback' // exact match with authorize call
Defensive patterns
Strategy: retry
Validate before calling
if (!clientId || !clientSecret || !code || redirectUri !== expectedRedirectUri) {
throw new Error('OAuth exchange prerequisites invalid');
} Try / catch
try {
const token = await gh.exchangeOAuthCode({ code, redirectUri });
} catch (e) {
if (e.message.startsWith('GitHub OAuth token exchange failed:')) {
const status = Number(e.message.match(/(\d+)$/)?.[1]);
if (status >= 500) retryWithBackoff();
else restartOauthFlow(); // 4xx: code/credentials/redirect_uri problem — do not retry the same code
} else throw e;
} Prevention
- Keep redirect_uri identical between the authorize redirect and the token exchange
- Never reuse authorization codes; always start a fresh OAuth flow on failure
- Verify client credentials against the GitHub OAuth App settings before deploying
- Check the GitHub status page for 5xx-caused failures before debugging app config
When it happens
Trigger: Exchanging an OAuth authorization code for an access token when GitHub responds with 4xx/5xx — most commonly 401 (wrong client_secret), 404 (wrong client_id), or 400 (expired/already-used code or redirect_uri mismatch).
Common situations: Mismatched redirect_uri between the authorize step and the token exchange; authorization code reused or older than ~10 minutes; incorrect/misconfigured GITHUB_CLIENT_SECRET; GitHub outage (5xx).
Related errors
- Slack OAuth HTTP error: ${tokenResponse.status} ${tokenRespo
- ${response.status} ${response.statusText}: ${text}
- Kimi For Coding device authorization failed: ${response.stat
- GitHub source control request failed: ${res.status}
- Token exchange failed: ${error}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/120db0672efc7340.
Report an issue: GitHub.