mastra-ai/mastra · error · HTTPException

Session expired

Error message

Session expired

What it means

This HTTP 401 error is thrown when `auth.refreshSession(sessionId)` resolves to null/undefined — the provider recognized the session ID but could not renew it, typically because the session expired server-side or no longer exists.

Source

Thrown at packages/server/src/server/handlers/auth.ts:633

      if (
        !auth ||
        !implementsInterface<ISessionProvider>(auth, 'refreshSession') ||
        !implementsInterface<ISessionProvider>(auth, 'getSessionIdFromRequest')
      ) {
        throw new HTTPException(404, { message: 'Session refresh not configured' });
      }

      // Get session ID from request
      const sessionId = auth.getSessionIdFromRequest(request);
      if (!sessionId) {
        throw new HTTPException(401, { message: 'No session' });
      }

      // Refresh the session
      const newSession = await auth.refreshSession(sessionId);
      if (!newSession) {
        throw new HTTPException(401, { message: 'Session expired' });
      }

      // Build response with new session headers
      const headers = new Headers({ 'Content-Type': 'application/json' });
      if (implementsInterface<ISessionProvider>(auth, 'getSessionHeaders')) {
        const sessionHeaders = auth.getSessionHeaders(newSession);
        for (const [key, value] of Object.entries(sessionHeaders)) {
          headers.append(key, value);
        }
      }

      return new Response(JSON.stringify({ success: true }), {
        status: 200,
        headers,
      });
    } catch (error) {
      if (error instanceof HTTPException) throw error;
      return handleError(error, 'Error refreshing session');

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Treat 401 as sign-out: redirect the user to the sign-in flow to establish a fresh session.
  2. Refresh sessions proactively before TTL expiry rather than after; increase session/refresh TTL in provider config if appropriate.
  3. If sessions vanish on deploy, use a persistent session store instead of in-memory.

Example fix

// before
const res = await refreshSession(); // throws 401 after expiry
// after
const res = await refreshSession();
if (res.status === 401) redirectToSignIn();
Defensive patterns

Strategy: fallback

Validate before calling

// optionally track last-refresh time client-side and refresh before typical TTL
const REFRESH_INTERVAL_MS = 10 * 60 * 1000;
if (Date.now() - lastRefreshAt > REFRESH_INTERVAL_MS) scheduleRefresh();

Try / catch

try {
  const res = await fetch('/api/auth/session/refresh', { method: 'POST', credentials: 'include' });
  if (res.status === 401) {
    await signInAgain(); // session expired: full re-auth
  }
} catch (e) { redirectToSignIn(); }

Prevention

When it happens

Trigger: POST the session refresh endpoint with a session ID that the provider cannot refresh: expired beyond the refresh window, revoked, or deleted from the session store.

Common situations: User idle past session TTL; server restarted with an in-memory session store losing all sessions; refresh attempted after absolute expiry (refresh tokens only renew within limits).

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/1d0cb285c12786f7. Report an issue: GitHub.