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 completed

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Force re-authentication for the user — an invalid_grant means the stored refresh token is no longer usable
  2. Verify COMPANION_ONEDRIVE_KEY and COMPANIED_ONEDRIVE_SECRET (check exact env names in your Companion config) match the Azure app registration
  3. Log the token response body to identify the OAuth error code Microsoft returns
  4. 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

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


AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28). Data as JSON: /api/errors/58884b4757d1f25a. Report an issue: GitHub.