transloadit/uppy · error · Error
Unexpected OneDrive token refresh response
Error message
Unexpected OneDrive token refresh response
What it means
After POSTing to OneDrive's token refresh endpoint, the response is parsed and body['access_token'] must be a string. If it is absent or not a string, Companion throws 'Unexpected OneDrive token refresh response', indicating the OAuth refresh failed (typically an expired/revoked refresh token or bad client credentials) and Microsoft returned an error body instead of a token.
Source
Thrown at packages/@uppy/companion/src/server/provider/onedrive/index.ts:194
'provider.onedrive.token.refresh.error',
async () => {
const body = await getOauthClient()
.post('oauth20_token.srf', {
responseType: 'json',
form: {
refresh_token: refreshToken,
grant_type: 'refresh_token',
client_id: clientId,
client_secret: clientSecret,
redirect_uri: redirectUri,
},
})
.json<Record<string, unknown>>()
const accessToken =
typeof body['access_token'] === 'string' ? body['access_token'] : null
if (!accessToken) {
throw new Error('Unexpected OneDrive token refresh response')
}
return { accessToken }
},
)
}
async #withErrorHandling<T>(tag: string, fn: () => Promise<T>): Promise<T> {
return withProviderErrorHandling({
fn,
tag,
providerName: OneDrive.oauthProvider,
isAuthError: (response) => response.statusCode === 401,
isUserFacingError: (response) =>
typeof response.statusCode === 'number' &&
[400, 403].includes(response.statusCode),
// onedrive gives some errors here that the user might want to know about
// e.g. these happen if you try to login to a users in an organization,
// without an Office365 licence or OneDrive account setup completedView on GitHub (pinned to 5d4dedd02a)
Solutions
- Force re-authentication for the user — an invalid_grant means the stored refresh token is no longer usable
- Verify COMPANION_ONEDRIVE_KEY and COMPANIED_ONEDRIVE_SECRET (check exact env names in your Companion config) match the Azure app registration
- Log the token response body to identify the OAuth error code Microsoft returns
- Ensure redirect URIs and consent scopes in Azure match what Companion requests
Example fix
// before
const { accessToken } = await onedriveProvider.refreshToken({ refreshToken, companion })
// after
try {
const { accessToken } = await onedriveProvider.refreshToken({ refreshToken, companion })
} catch {
// refresh failed -> make the user sign in again
throw new ProviderAuthError('OneDrive session expired', 401)
} Defensive patterns
Strategy: try-catch
Validate before calling
if (typeof refreshToken !== 'string' || refreshToken.length === 0) {
throw new ProviderAuthError('no refresh token', 401)
} Type guard
const hasRefreshToken = (s: unknown): s is { refreshToken: string } =>
typeof (s as { refreshToken?: unknown })?.refreshToken === 'string' Try / catch
try { await provider.refreshToken(args) } catch (e) { if (e instanceof Error && e.message === 'Unexpected OneDrive token refresh response') { await restartMicrosoftOAuth() } throw e } Prevention
- Redirect to re-auth on first refresh failure rather than retrying
- Keep Azure app credentials in sync
- Monitor Microsoft identity platform error codes in logs
When it happens
Trigger: Calling refreshToken() with a revoked or expired Microsoft refresh token; Microsoft identity platform returning { error: 'invalid_grant' }; OneDrive client id/secret mismatch in Companion config.
Common situations: User removed the app from their Microsoft account; admin revoked consent in Azure AD; COMPANION_ONEDRIVE_KEY/SECRET rotated or wrong; single-page session outliving the refresh token's validity.
Related errors
- Missing access_token
- Not implemented
- Missing access_token
- Missing S3 object key for aborting upload
- Missing S3 object key for resuming upload
AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28).
Data as JSON: /api/errors/58884b4757d1f25a.
Report an issue: GitHub.