toeverything/AFFiNE · warning · BadRequest
bad_request
bad_request
Error message
Invalid origin: ${origin}, referer: ${referer} What it means
The WebSocket telemetry gateway applies the identical origin allow-list check to the socket handshake headers before accepting a 'telemetry:batch' event. Browsers always attach an Origin to the handshake, so a page loaded from a non-allow-listed domain gets every telemetry batch rejected with bad_request.
Solutions
- Allow-list the origin the page is served from (telemetry origins and/or url.allowedOrigins config)
- Verify the handshake actually carries the expected Origin/Referer (proxy inspection)
- Non-browser clients should connect without spoofing an Origin, or add their declared origin to the allow-list
Defensive patterns
Strategy: validation
Validate before calling
// gate ws telemetry emission on the handshake origin
const origin = new URL(socket.io.uri, location.href).origin;
if (!allowedOrigins.includes(origin)) {
socket.off('telemetry:batch'); // avoid guaranteed rejections
} Type guard
function isHandshakeAllowed(handshakeOrigin: string | undefined, allowed: string[]): boolean {
return !handshakeOrigin || allowed.includes(handshakeOrigin);
} Prevention
- Allow-list every origin that opens telemetry sockets in server config
- Non-browser ws clients should not set an Origin header unless it is allow-listed
- Check handshake headers at the proxy to catch rewrites before they reach the gateway
When it happens
Trigger: Emitting 'telemetry:batch' from a page whose handshake Origin is not in allowedOrigins; a Referer whose origin is unlisted when Origin is absent; server-side ws clients forging an Origin header that is not allow-listed.
Common situations: App served from a new domain after config drift; embedding the app on another site; proxies rewriting handshake headers during the upgrade request.
Understand the failure class
Background: BAD_REQUEST error code: request rejected as invalid (HTTP 400) - causes and fixes across libraries — this error's family across 8 libraries.
Related errors
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/ae2716d106a1adfe.
Report an issue: GitHub.
Appendix: source
Thrown at packages/backend/server/src/core/telemetry/gateway.ts:37
type EventResponse<Data = any> = [Data] extends [never]
? { data?: never }
: { data: Data };
@WebSocketGateway()
@UseInterceptors(ClsInterceptor)
export class TelemetryGateway {
constructor(private readonly telemetry: TelemetryService) {}
@SubscribeMessage('telemetry:batch')
async onBatch(
@CurrentUser() user: CurrentUser,
@ConnectedSocket() client: Socket,
@MessageBody() batch: TelemetryBatch
): Promise<EventResponse<TelemetryAck>> {
const origin = client.handshake.headers.origin;
const referer = client.handshake.headers.referer;
if (!this.telemetry.isOriginAllowed(origin, referer)) {
throw new BadRequest(`Invalid origin: ${origin}, referer: ${referer}`);
}
const ack = await this.telemetry.collectBatch({
...batch,
transport: 'ws',
events: batch?.events?.map(event => ({
...event,
userId: event.userId ?? user?.id,
})),
});
return { data: ack };
}
}
View on GitHub (pinned to b4c8548c09)