toeverything/AFFiNE · error · SessionAccessTokenError

ACCESS_TOKEN_EXPIRED

ACCESS_TOKEN_EXPIRED

Error message

ACCESS_TOKEN_EXPIRED

What it means

In verify(), after the key id is parsed and the signing key is loaded, verifyAuthSessionAccessToken is checked; any status other than 'valid' that isn't 'expired' maps to ACCESS_TOKEN_INVALID, i.e. the token failed signature/structural verification against the retrieved key secret.

Solutions

  1. The access token has expired — call the refresh/session endpoint to get a new token before retrying.
  2. Implement automatic token refresh on ACCESS_TOKEN_EXPIRED responses instead of forcing the user to sign in again.
  3. Check client clock skew; a badly skewed clock can make valid tokens appear expired.

Example fix

if (res.status === 401 && body.includes('ACCESS_TOKEN_EXPIRED')) {
  await refreshSession(); // POST /api/auth/session/refresh
  return retry(originalRequest);
}
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at packages/backend/server/src/core/auth/access-token.ts:80 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18). Data as JSON: /api/errors/a2f98e61690fa3a6. Report an issue: GitHub.

Appendix: source

Thrown at packages/backend/server/src/core/auth/access-token.ts:80

    }
    throw new AuthSessionTemporarilyUnavailable();
  }

  async verify(token: string): Promise<AuthSessionPrincipal> {
    const keyId = authSessionAccessTokenKeyId(token);
    if (!keyId) {
      throw new SessionAccessTokenError('ACCESS_TOKEN_INVALID');
    }
    const key = await this.keys.verify(keyId);
    if (!key) throw new SessionAccessTokenError('ACCESS_TOKEN_INVALID');
    const verified = verifyAuthSessionAccessToken(
      token,
      keyId,
      key.secret,
      Math.floor(Date.now() / 1000)
    );
    if (verified.status !== 'valid') {
      throw new SessionAccessTokenError(
        verified.status === 'expired'
          ? 'ACCESS_TOKEN_EXPIRED'
          : 'ACCESS_TOKEN_INVALID'
      );
    }
    const { authSessionId, userId } = verified;
    if (!authSessionId || !userId) {
      throw new SessionAccessTokenError('ACCESS_TOKEN_INVALID');
    }
    const authSession = await this.models.authSession.get(authSessionId);
    if (!authSession || authSession.userSession.userId !== userId) {
      throw new SessionAccessTokenError('ACCESS_TOKEN_INVALID');
    }
    if (authSession.revokedAt) {
      throw new SessionAccessTokenError('AUTH_SESSION_REVOKED');
    }
    const now = new Date();
    if (

View on GitHub (pinned to b4c8548c09)