danny-avila/LibreChat · error · Error
Failed to authenticate OAuth tool
Error message
Failed to authenticate OAuth tool
What it means
Thrown during an Action's OAuth token exchange/refresh when the underlying token call rejects. The original error is logged; a generic message is re-thrown so callers see a stable failure type rather than leaking provider-specific detail.
Source
Thrown at api/server/services/ActionService.js:302
data.delta.auth = undefined;
data.delta.expires_at = undefined;
const successEventData = { event: GraphEvents.ON_RUN_STEP_DELTA, data };
if (streamId) {
await GenerationJobManager.emitChunk(streamId, successEventData, {
expectedCreatedAt: jobCreatedAt,
});
} else {
sendEvent(res, successEventData);
}
await sleep(3000);
metadata.oauth_access_token = result.access_token;
metadata.oauth_refresh_token = result.refresh_token;
const expiresAt = new Date(Date.now() + result.expires_in * 1000);
metadata.oauth_token_expires_at = expiresAt.toISOString();
} catch (error) {
const errorMessage = 'Failed to authenticate OAuth tool';
logger.error(errorMessage, error);
throw new Error(errorMessage);
}
};
const tokenPromises = [];
tokenPromises.push(findToken({ userId, type: 'oauth', identifier }));
tokenPromises.push(
findToken({
userId,
type: 'oauth_refresh',
identifier: `${identifier}:refresh`,
}),
);
const [tokenData, refreshTokenData] = await Promise.all(tokenPromises);
if (tokenData) {
// Valid token exists, add it to metadata for setAuth
metadata.oauth_access_token = await decryptV2(tokenData.token);
if (refreshTokenData) {View on GitHub (pinned to 5ff282f900)
Solutions
- Re-run the OAuth authorization flow to obtain a fresh access+refresh token pair.
- Verify the action's client_id/client_secret and redirect_uri match the provider's app config.
- Check provider response in the logs (the original error is logged before this message) for the exact OAuth error.
- Ensure server clock is synchronized (NTP) so token expiry is computed correctly.
Defensive patterns
Strategy: retry
Try / catch
try { await validateAndUpdateTool(...); }
catch (e) {
if (/Failed to authenticate OAuth tool/.test(e.message)) {
await requestReauthorization();
return;
}
throw e;
} Prevention
- Refresh tokens proactively before expiry (use oauth_token_expires_at).
- Log the wrapped provider error so the root cause is diagnosable.
- Keep client secrets current; rotate on a schedule.
When it happens
Trigger: The OAuth token endpoint returns an error, the authorization code is invalid/expired, the refresh token is revoked, or the redirect_uri/client credentials do not match the registered app. Surfaces during validateAndUpdateTool when refreshing or minting a token for an authenticated action.
Common situations: Expired refresh token after a long idle period; rotated OAuth client secret not updated; clock skew rejecting token expiry; provider-side rate limiting or outage during token exchange.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- OAuth flow not found
- Authentication failed: ${error.message}
- [MCP][${serverName}][${toolName}] upstream authentication fa
- [MCP][${serverName}][${toolName}] OAuth authentication requi
- User must be authenticated via OpenID to perform OBO token e
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/39f9253603c2eff3.
Report an issue: GitHub.