toeverything/AFFiNE · error · AuthenticationRequired

authentication_required

authentication_required

Error message

You must sign in first to access this resource.

What it means

The user realtime provider backs live queries over the user's profile and settings rooms. Its helpers call assertAuthenticated, which throws authentication_required when the current user object is missing - i.e. the socket/request is anonymous (never signed in, session expired, or token not attached).

Solutions

  1. Wait for a successful sign-in (session resolved) before subscribing to realtime user events
  2. On this error, re-authenticate, then reconnect and resubscribe
  3. Gate realtime subscription setup behind your auth-state store

Example fix

// before
registry.subscribe('user:profile', handler); // anonymous socket throws

// after
if (isAuthenticated(user)) {
  registry.subscribe('user:profile', handler);
}
Defensive patterns

Strategy: validation

Validate before calling

// subscribe only when a session is present
if (!session.user) {
  throw new Error('sign in before subscribing to realtime user events');
}
await subscribeUserRealtime(session.user.id);

Type guard

function isAuthenticated(user?: { id: string } | null): user is { id: string } {
  return !!user?.id;
}

Try / catch

try {
  await subscribeUserRealtime(userId);
} catch (e) {
  if (e?.code === 'authentication_required') {
    await reauthenticate();
    await subscribeUserRealtime(userId);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Subscribing to realtime user profile/settings rooms before sign-in completes; a session that expired or was revoked while the socket stayed connected; auth middleware failing to attach the user so the realtime path sees undefined.

Common situations: Frontend booting realtime subscriptions during the auth handshake; long-lived sockets surviving past token expiry; tokens invalidated by sign-out-everywhere.

Related errors


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

Appendix: source

Thrown at packages/backend/server/src/core/user/realtime.ts:24

import { z } from 'zod';

import { AuthenticationRequired, OnEvent, UserNotFound } from '../../base';
import { Feature, Models } from '../../models';
import { sessionUser } from '../auth/service';
import { AvailableUserFeatureConfig } from '../features/types';
import { registerRealtimeLiveQuery } from '../realtime/provider';
import { RealtimePublisher } from '../realtime/publisher';
import { RealtimeRegistry } from '../realtime/registry';
import {
  realtimeUserProfileRoom,
  realtimeUserSettingsRoom,
} from '../realtime/rooms';

const emptyInput = z.object({}).strict();

function assertAuthenticated(user?: { id: string }) {
  if (!user) {
    throw new AuthenticationRequired();
  }
  return user;
}

@Injectable()
export class UserRealtimeProvider
  extends AvailableUserFeatureConfig
  implements OnModuleInit
{
  constructor(
    private readonly models: Models,
    @Optional() private readonly registry?: RealtimeRegistry,
    @Optional() private readonly publisher?: RealtimePublisher
  ) {
    super();
  }

  onModuleInit() {

View on GitHub (pinned to b4c8548c09)