toeverything/AFFiNE · critical

AUTHENTICATION_REQUIRED

Error message

AUTHENTICATION_REQUIRED

What it means

Error('AUTHENTICATION_REQUIRED') thrown from the authorize callback of the copilot.delegated.tool.requested realtime topic when there is no authenticated user on the socket. Subscribing to this topic (which streams tool-call requests to a delegating client) is only valid for authenticated connections; the guard runs before the room is computed.

Source

Thrown at packages/backend/server/src/plugins/copilot/delegated/realtime.ts:136

    });
    this.registry.registerRequest({
      name: 'copilot.delegated.tool.respond',
      input: responseSchema,
      handle: async (user, response) => {
        if (!user) return { accepted: false };
        const accepted = this.delegated.receive(user.id, response);
        this.event.broadcast('copilot.delegated.tool.responded', {
          userId: user.id,
          response,
        });
        return { accepted };
      },
    });
    this.registry.registerTopic({
      name: 'copilot.delegated.tool.requested',
      input: z.object({ clientId: z.string().min(1).max(128) }).strict(),
      authorize: async user => {
        if (!user) throw new Error('AUTHENTICATION_REQUIRED');
      },
      room: (user, input) => {
        if (!user) throw new Error('AUTHENTICATION_REQUIRED');
        return realtimeUserRoom(user.id, `copilot:${input.clientId}`);
      },
    });
  }
}

View on GitHub (pinned to b4c8548c09)

Solutions

  1. Authenticate the realtime connection (valid token/cookie) before subscribing to the topic
  2. Re-authenticate and resubscribe when the token expires mid-session
  3. In client code, gate topic subscription on the connection's authenticated state

Example fix

// before
socket.subscribe('copilot.delegated.tool.requested', { clientId }); // anonymous socket

// after
await socket.authenticate(token);
socket.subscribe('copilot.delegated.tool.requested', { clientId });
Defensive patterns

Strategy: validation

Validate before calling

if (!socket.isAuthenticated) {
  await socket.authenticate(getToken());
}
await socket.subscribe('copilot.delegated.tool.requested', { clientId });

Try / catch

try {
  await socket.subscribe('copilot.delegated.tool.requested', { clientId });
} catch (e) {
  if (e.message === 'AUTHENTICATION_REQUIRED') {
    await reauthenticate();
    await socket.subscribe('copilot.delegated.tool.requested', { clientId });
  } else throw e;
}

Prevention

When it happens

Trigger: Subscribing to topic copilot.delegated.tool.requested over an anonymous/unauthenticated websocket; token expired before subscribe; auth handshake skipped by a custom client.

Common situations: Client subscribes before completing the auth flow; session cookie/JWT expired and the socket silently downgraded to anonymous; load-test client forgot credentials.

Understand the failure class

Related errors


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