cube-js/cube · error · CubejsHandlerError

Invalid authorization message format

Error message

Invalid authorization message format

What it means

When a WebSocket message contains an 'authorization' property, it must match the authMessageSchema (Zod): expected fields like token (and messageId per schema). Failures throw CubejsHandlerError(400, 'Invalid authorization message format') with a Zod-derived detail string listing the bad path and reason.

Source

Thrown at packages/cubejs-api-gateway/src/ws/subscription-server.ts:69

  protected deserializeMessage(message: any): any {
    try {
      return JSON.parse(message);
    } catch (e: any) {
      throw new CubejsHandlerError(400, 'Invalid JSON payload', e.message);
    }
  }

  protected mapZodError(error: ZodError): string {
    return error.issues
      .map(e => (e.path.length ? `${e.path.join('.')}: ${e.message}` : e.message))
      .join(', ');
  }

  protected validateMessage(message: object): WsMessage {
    if ('authorization' in message) {
      const result = authMessageSchema.safeParse(message);
      if (!result.success) {
        throw new CubejsHandlerError(400, 'Invalid authorization message format', this.mapZodError(result.error));
      }

      return result.data;
    }

    if ('unsubscribe' in message) {
      const result = unsubscribeMessageSchema.safeParse(message);
      if (!result.success) {
        throw new CubejsHandlerError(400, 'Invalid unsubscribe message format', this.mapZodError(result.error));
      }

      return result.data;
    }

    const result = methodMessageSchema.safeParse(message);
    if (!result.success) {
      throw new CubejsHandlerError(400, 'Invalid message format', this.mapZodError(result.error));
    }

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Send the auth message in the schema's exact shape, e.g. { authorization: { token: '<jwt>' }, messageId: 'auth-1' } (check authMessageSchema in this package version).
  2. Read the Zod detail after the error message — it names the exact field and rule violated.
  3. Use the official @cubejs-client/ws-transport (WebSocketTransport) rather than hand-building protocol messages.
  4. Bump the client and server packages to matching versions if the handshake shape changed in an upgrade.

Example fix

// before
socket.send(JSON.stringify({ messageId: '1', authorization: 'my-jwt' }));
// after
socket.send(JSON.stringify({ messageId: '1', authorization: { token: 'my-jwt' } }));
Defensive patterns

Strategy: validation

Validate before calling

function isValidAuthMessage(msg: unknown): boolean {
  const m = msg as any;
  return typeof m === 'object' && m !== null &&
    typeof m.messageId === 'string' &&
    typeof m.authorization === 'object' && m.authorization !== null &&
    typeof m.authorization.token === 'string';
}

Type guard

function isAuthMessage(m: unknown): m is { messageId: string, authorization: { token: string } } {
  return typeof m === 'object' && m !== null && 'authorization' in m &&
    typeof (m as any).authorization?.token === 'string';
}

Try / catch

try {
  await handleMessage(frame);
} catch (e) {
  if (e.status === 400 && e.error === 'Invalid authorization message format') {
    console.error('Auth frame rejected:', e.message); // Zod detail appended
  } else throw e;
}

Prevention

When it happens

Trigger: Sending { authorization: ... } where authorization is not the expected object — e.g. authorization as a raw token string, missing required token/messageId fields, or wrong types per authMessageSchema.

Common situations: Custom WS clients passing { authorization: 'eyJ...' } instead of the schema's object shape; SDK version drift where the auth handshake shape changed; manually replaying protocol messages from docs of an older Cube version.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/91888eb6d6d7f07c. Report an issue: GitHub.