Troubleshoot OAuth errors
Diagnose and resolve common OAuth authentication and token refresh errors
Learn how to diagnose and resolve common OAuth authentication and token refresh errors that may occur during integration.
Use this guide when you encounter OAuth errors during authorization, token exchange, or token refresh operations. This troubleshooting guide focuses on the most common production issues and provides detailed resolution steps. For a complete list of OAuth error codes and their definitions, refer to the Airwallex OAuth Error Codes API.
Common refresh token errors
invalid_grant: OAuth 2.0 Parameter: refresh_token
Error message: invalid_grant: OAuth 2.0 Parameter: refresh_token or invalid or expired refresh token
HTTP status: 400 Bad Request
Common causes:
- Refresh token has expired (older than 90 days).
- Refresh token has been revoked due to token reuse outside the grace period.
Resolution steps:
- Do not retry with the same refresh token.
- Check if the refresh token is within its 90-day lifetime using the
refresh_token_expires_invalue from your last successful refresh. - If within 90 days, check your application logs for signs of token reuse or concurrent refresh requests.
- Re-authenticate the user through the full authorization flow.
Prevention:
- Proactively refresh tokens every 60-80 days, well before the 90-day expiration.
- Always store only the latest refresh token.
- Implement proper token rotation logic in your application.
Concurrent refresh request issues
too_many_requests
HTTP status: 429 Too Many Requests
Error: too_many_requests: Concurrent token refresh is not allowed.
Cause:
You attempted to refresh a token while another refresh request for the same token was already in progress.
Resolution:
- Wait briefly (1-2 seconds) before retrying the request.
- Implement request synchronization in your application using a lock or queue mechanism to ensure only one token refresh happens at a time.
- If multiple application instances exist, use distributed locking (for example, Redis locks, database locks).
- Consider implementing a token refresh coordinator service that handles all refresh operations.
- Use the implementation pattern shown below to queue refresh requests.
Prevention:
- Design your refresh logic to be single-threaded per account.
- Implement request deduplication.
- Cache the new access token and reuse it across requests until it expires (5 minutes).
- Use mutex locks or similar synchronization primitives.
Example implementation pattern:
1// Pseudocode for preventing concurrent refreshes2class TokenManager {3 private refreshPromises = new Map();45 async getValidAccessToken(accountId) {6 // Check if token is still valid7 if (this.isTokenValid(accountId)) {8 return this.getStoredAccessToken(accountId);9 }1011 // Check if refresh is already in progress12 if (this.refreshPromises.has(accountId)) {13 return this.refreshPromises.get(accountId);14 }1516 // Start new refresh and store promise17 const refreshPromise = this.refreshToken(accountId)18 .finally(() => this.refreshPromises.delete(accountId));1920 this.refreshPromises.set(accountId, refreshPromise);21 return refreshPromise;22 }23}
For a complete implementation including token validity checking, see Check token validity.
Connection unexpectedly disconnected
Symptoms:
- Users report integration "stops working" intermittently.
- Must repeatedly disconnect and reconnect
- API calls fail with authentication errors.
- Payments or data syncing suddenly cease.
Common root causes:
- Token reuse: Application is not properly rotating refresh tokens
- Concurrent refreshes: Multiple application instances refreshing simultaneously
- Token expiration: Not proactively refreshing before 90-day expiration
- Role changes: Admin who granted consent lost admin privileges
Diagnostic steps:
- Check your logs for
invalid_granterrors during token refresh. - Verify you're storing and using only the latest refresh token.
- Confirm no concurrent refresh requests are occurring.
- Check the
refresh_token_expires_invalue to ensure the token hasn't expired. - Verify the authorizing user still has Owner, Admin, or Finance Admin access.
- Review your token refresh frequency - are you waiting until expiration?
Resolution:
- Fix token rotation logic to always use the latest token.
- Implement proper concurrency controls (see "Concurrent refresh requests" above).
- Add proactive token refresh every 60-80 days.
- Document role requirements for your users.
- If role changes occurred, have a current admin re-authorize.
Authorization flow errors
Redirect URI mismatch
Error: Authorization fails or returns error parameter
Cause:
The redirect URI in your authorization request doesn't match a whitelisted URI for your application.
Resolution:
Contact your Airwallex partnerships manager to whitelist additional redirect URIs. Ensure the redirect URI in your authorization request exactly matches the whitelisted value (including protocol, domain, path, and any trailing slashes).
Prevention:
- Maintain a list of your whitelisted redirect URIs.
- Validate redirect URIs in your application before initiating OAuth flow.
- Use environment variables to manage redirect URIs across development, staging, and production.
User declined authorization
Behavior:
User is redirected to your redirect_uri with an error parameter instead of an authorization code.
Example:
1https://<YOUR_REDIRECT_URI>/?error=access_denied&state=<YOUR_STATE>
Resolution:
Handle the error gracefully in your UI and allow users to retry authorization. This is expected behavior when users choose not to authorize your application.
Best practices:
- Display a clear message explaining why authorization is needed.
- Provide a "Try Again" or "Connect to Airwallex" button.
- Do not automatically retry - let users initiate the flow when ready.
Authorization code expired or invalid
Error: invalid_grant: OAuth 2.0 Parameter: code
Cause:
Authorization codes expire after 5 minutes or have already been used.
Resolution:
- Ensure you exchange the authorization code for tokens immediately after receiving it.
- Do not reuse authorization codes - they are single-use only.
- If the code has expired, prompt the user to re-authorize.
Network and service errors
500 Internal Server Error
Cause:
Temporary service issues on Airwallex's authentication services.
Resolution:
- Implement retry logic with exponential backoff (for example, retry after 1s, 2s, 4s, 8s).
- Maximum 3-5 retry attempts.
- If retries fail, display a user-friendly error and suggest trying again later.
Do not:
- Retry indefinitely.
- Retry 400-level errors (these are permanent failures).
503 Service Unavailable
Cause:
Airwallex services are temporarily unavailable or undergoing maintenance.
Resolution:
Same as 500 errors - implement retry logic with exponential backoff.
Network timeout or connection refused
Cause:
Network connectivity issues between your application and Airwallex APIs.
Resolution:
- Verify your network connectivity.
- Check firewall rules allow outbound HTTPS connections to
api.airwallex.com. - Implement retry logic with exponential backoff.
- Consider using the grace period (60 seconds) to retry token refresh if you're unsure whether the initial request succeeded.
Best practices for error handling
To minimize OAuth errors and maintain reliable connections:
Token management
-
Single-use token handling:
- Store only the latest refresh token.
- Replace old token immediately upon successful refresh.
- Do not reuse old tokens.
-
Proactive refresh:
- Refresh tokens every 60-80 days, not at 90-day expiration.
- Monitor
refresh_token_expires_invalues. - Alert your operations team when tokens approach expiration.
-
Concurrency control:
- Implement locking for refresh operations.
- Use single-threaded refresh logic per account.
- Queue requests that need tokens while refresh is in progress.
Error handling
-
Retry strategy:
- Implement exponential backoff for 500-level errors.
- Do not retry 400-level errors with the same token.
- Use a maximum of 3-5 retry attempts.
-
Logging and monitoring:
- Log all refresh failures with trace IDs.
- Track token refresh success rates.
- Alert on repeated refresh failures.
- Monitor token age and plan proactive refreshes.
-
User communication:
- Display clear error messages for authorization issues.
- Provide "Reconnect" functionality when tokens are revoked.
- Do not expose technical error details to end users.
Testing
-
Test token rotation:
- Verify your application uses the latest token after each refresh.
- Test with expired tokens to ensure proper error handling.
- Simulate concurrent refresh scenarios.
-
Test error scenarios:
- Invalid tokens.
- Expired tokens.
- Revoked tokens.
- Network failures during refresh.
Getting help
If you continue experiencing OAuth errors after following this guide:
Gather diagnostic information
Before contacting support, collect:
- Error messages and HTTP status codes
- Trace IDs from failed requests (found in error responses or logs)
- Timestamp of errors (in UTC)
- Your application client ID
- Affected account IDs (if known)
- Frequency of errors (one-time, intermittent, consistent)
Contact support
Email [email protected] with your diagnostic information.
For urgent production issues affecting multiple users, include "URGENT" in your subject line and provide:
- Number of affected users
- Business impact
- Steps already taken to resolve
See also
To implement OAuth or understand permission requirements, refer to: