Budibase/budibase · error · Error
Failed to exchange Microsoft OAuth code
Error message
Failed to exchange Microsoft OAuth code
What it means
The token exchange POST to Microsoft's token endpoint returned a non-success status or an error payload; the controller logs status/error details and throws this Error. The code-for-token exchange did not produce usable credentials.
Source
Thrown at packages/server/src/api/controllers/ai/sharepointAuth.ts:158
},
body: new URLSearchParams({
client_id: clientId,
client_secret: clientSecret,
grant_type: "authorization_code",
code,
redirect_uri: callbackUrl,
scope: DEFAULT_SCOPE,
}),
})
const tokenPayload = await tokenResponse.json()
if (!tokenResponse.ok) {
console.error("Microsoft OAuth token exchange failed", {
appId,
status: tokenResponse.status,
error: tokenPayload?.error,
hasDescription: !!tokenPayload?.error_description,
})
throw new Error("Failed to exchange Microsoft OAuth code")
}
const refreshToken = tokenPayload?.refresh_token
const accessToken = tokenPayload?.access_token
if (!refreshToken) {
throw new Error("Microsoft OAuth response did not include a refresh token")
}
if (!accessToken) {
throw new Error("Microsoft OAuth response did not include an access token")
}
const expiresIn = Number(tokenPayload?.expires_in || 0)
const tokenType = tokenPayload?.token_type || "Bearer"
const bearerToken = `${tokenType} ${accessToken}`
let account = "unknown"
try {
const meResponse = await fetch(View on GitHub (pinned to a81a902e9a)
Solutions
- Check server logs for the 'Microsoft OAuth token exchange failed' entry showing status and error (e.g. invalid_grant, invalid_client).
- Ensure the redirect_uri, client_id, and tenant in the token request exactly match the authorize request.
- Restart the OAuth flow to get a fresh authorization code; codes cannot be reused.
- Verify MICROSOFT_CLIENT_SECRET is current and correctly loaded in the server environment.
Example fix
// before // token request with redirect_uri that differs from the authorize call redirect_uri: 'http://localhost:10000/callback' // after redirect_uri: 'https://app.example.com/api/ai/sharepoint/callback' // identical to authorize request
Defensive patterns
Strategy: retry
Validate before calling
// ensure a fresh, unused code: start a new flow if the callback has already been processed once
Try / catch
try {
await completeSharePointAuth(ctx)
} catch (e) {
if (e.message === 'Failed to exchange Microsoft OAuth code') {
// check logs for invalid_grant/invalid_client, then restart the OAuth flow with a new code
} else throw e
} Prevention
- Use the identical redirect_uri in authorize and token requests.
- Never reuse authorization codes; they are single-use and short-lived.
- Rotate and verify MICROSOFT_CLIENT_SECRET; watch for invalid_client errors.
- Monitor the token endpoint status in logs to distinguish config vs transient failures.
When it happens
Trigger: Authorization code already used or expired (codes are single-use, short-lived); wrong redirect_uri sent in the token request; invalid client secret; tenant mismatch between authorize and token endpoints; network/proxy failure to login.microsoftonline.com.
Common situations: Replaying an auth code after a retry; redirect_uri differing between authorize and token calls (invalid_grant); expired or rotated MICROSOFT_CLIENT_SECRET (invalid_client); clock skew affecting code validity.
Related errors
- No Microsoft datasource configuration found
- Microsoft OAuth callback is missing state
- Microsoft OAuth state is invalid or expired
- Microsoft OAuth authorization failed
- Microsoft OAuth callback is missing the authorization code
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/911214d087502af3.
Report an issue: GitHub.