toeverything/AFFiNE · error · AuthSessionTemporarilyUnavailable

auth_session_temporarily_unavailable

auth_session_temporarily_unavailable

Error message

Auth session service is temporarily unavailable.

What it means

sign retries reading the active signing key up to SIGNING_KEY_RETRY_LIMIT times; AuthSessionTemporarilyUnavailable is thrown when the key keeps rotating between read and check, meaning token signing must be attempted again shortly.

Solutions

  1. This is a transient 503 — retry the request after a short backoff; the auth session store (e.g. Redis/DB) is briefly unreachable.
  2. Check server logs for connectivity problems to the session storage backend.
  3. If it persists, verify the database/redis connection config for the auth module.

Example fix

async function withRetry(fn: () => Promise<Response>) {
  for (let i = 0; i < 3; i++) {
    const res = await fn();
    if (res.status !== 503) return res;
    await new Promise(r => setTimeout(r, 2 ** i * 200));
  }
  throw new Error('Auth service unavailable');
}
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at packages/backend/server/src/core/auth/access-token.ts:63 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/f6d923bd007d26cc. Report an issue: GitHub.

Appendix: source

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

    const ttl = this.config.auth.token.accessTokenTtl;
    for (let attempt = 0; attempt < SIGNING_KEY_RETRY_LIMIT; attempt++) {
      const issuedAt = Math.floor(Date.now() / 1000);
      const expiresAtSeconds = issuedAt + ttl;
      const expiresAt = new Date(expiresAtSeconds * 1000);
      const key = await this.keys.active();
      const token = signAuthSessionAccessToken(
        userId,
        authSessionId,
        key.id,
        key.secret,
        issuedAt,
        expiresAtSeconds
      );
      if ((await this.keys.active()).id === key.id) {
        return { token, expiresAt };
      }
    }
    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'

View on GitHub (pinned to b4c8548c09)