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
- Wait for a successful sign-in (session resolved) before subscribing to realtime user events
- On this error, re-authenticate, then reconnect and resubscribe
- 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
- Gate realtime subscriptions behind the auth-state store, not the page lifecycle
- Handle token expiry on long-lived sockets by re-authenticating and resubscribing
- Do not attempt anonymous realtime subscriptions - the provider requires a user by design
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
- INVALID_DELEGATED_EDITOR_SESSION
- authentication_required
- AUTHENTICATION_REQUIRED
- unsupported_client_version
- -32000
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)