danny-avila/LibreChat · error · Error
OAuth flow not found
Error message
OAuth flow not found
What it means
Thrown in the Action OAuth callback after CSRF validation succeeds but flowManager.getFlowState returns nothing. The transient OAuth flow record (created at the start of the flow) is no longer present, so the authorization code cannot be exchanged safely.
Source
Thrown at api/server/routes/actions.js:99
identifier = `${decodedState.user}:${action_id}`;
if (
!validateOAuthCsrf(req, res, identifier, OAUTH_CSRF_COOKIE_PATH) &&
!validateOAuthSession(req, decodedState.user)
) {
logger.error('[Action OAuth] CSRF validation failed: no valid CSRF or session cookie', {
identifier,
hasCsrfCookie: !!req.cookies?.[OAUTH_CSRF_COOKIE],
hasSessionCookie: !!req.cookies?.[OAUTH_SESSION_COOKIE],
});
await flowManager.failFlow(identifier, 'oauth', 'CSRF validation failed');
return res.redirect(`${basePath}/oauth/error?error=csrf_validation_failed`);
}
const flowState = await flowManager.getFlowState(identifier, 'oauth');
if (!flowState) {
throw new Error('OAuth flow not found');
}
const tokenData = await getAccessToken(
{
code,
userId: decodedState.user,
identifier,
client_url: flowState.metadata.client_url,
redirect_uri: flowState.metadata.redirect_uri,
token_exchange_method: flowState.metadata.token_exchange_method,
allowedAddresses: flowState.metadata.allowedAddresses,
/** Encrypted values */
encrypted_oauth_client_id: flowState.metadata.encrypted_oauth_client_id,
encrypted_oauth_client_secret: flowState.metadata.encrypted_oauth_client_secret,
},
{
findToken,
updateToken,View on GitHub (pinned to 5ff282f900)
Solutions
- Re-initiate the OAuth flow from the start so a fresh flow state is created.
- Increase the OAuth flow TTL if users consistently run past it on slow consent screens.
- Use a durable flow store (DB/redis) instead of in-memory so flows survive restarts.
- Detect duplicate callbacks and short-circuit before this code path.
Defensive patterns
Strategy: try-catch
Validate before calling
const flowState = await flowManager.getFlowState(identifier, 'oauth');
if (!flowState) {
return res.redirect(`${basePath}/oauth/error?error=flow_not_found`);
} Try / catch
try { /* callback handler */ }
catch (e) {
if (/OAuth flow not found/.test(e.message)) {
return res.redirect(`${basePath}/oauth/error?error=expired_flow`);
}
throw e;
} Prevention
- Use a persistent flow store (redis/db) rather than in-memory.
- Set a flow TTL longer than the slowest realistic consent.
- Idempotently handle replayed callback URLs.
When it happens
Trigger: The OAuth flow state expired or was evicted from its store before the callback returned; a duplicate/old callback hits the endpoint after the flow was completed or failed; the flow was never created (callback reached without a matching identifier).
Common situations: User takes a long time on the OAuth consent screen and the flow TTL elapses; replayed callback URL (refresh/bookmark); flow store restart or flush (e.g. in-memory store lost on redeploy); clock skew between issuer and callback.
Related errors
- Failed to authenticate OAuth tool
- Authentication failed: ${error.message}
- Trouble deleting Assistant Actions for Assistant ID: ${assis
- Invalid avatar URL
- Graph token acquisition failed: ${error.message}
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/5cb8de469b4da408.
Report an issue: GitHub.