cube-js/cube · error · UserError

messageId is required

Error message

messageId is required

What it means

Validation guard in SubscriptionServer.handleMessage: a WebSocket message that is neither a handshake nor an unsubscribe must carry a `messageId` so responses can be correlated with subscriptions; this sentinel UserError fires when it is absent, and the error is sent back over the socket rather than crashing the connection.

Source

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

        const acceptanceResult = await this.contextAcceptor(authContext);
        if (!acceptanceResult.accepted) {
          this.sendMessage(connectionId, acceptanceResult.rejectMessage);
          return;
        }

        await this.subscriptionStore.setAuthContext(connectionId, authContext);
        this.sendMessage(connectionId, { handshake: true });
        return;
      }

      if ('unsubscribe' in message) {
        await this.subscriptionStore.unsubscribe(connectionId, message.unsubscribe);
        return;
      }

      if (!message.messageId) {
        throw new UserError('messageId is required');
      }

      authContext = await this.subscriptionStore.getAuthContext(connectionId);
      if (!authContext) {
        await this.sendMessage(
          connectionId,
          {
            messageId: message.messageId,
            message: { error: 'Not authorized' },
            status: 403
          }
        );
        return;
      }

      if (!message.method) {
        throw new UserError('Method is required');
      }

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Include a unique messageId string in every subscription message sent over the WebSocket.
  2. Check that the client SDK serializes the message correctly and does not drop messageId.

Example fix

// before
socket.send(JSON.stringify({ method: 'load', query }));
// after
socket.send(JSON.stringify({ messageId: 'q-1', method: 'load', query }));
Defensive patterns

Strategy: validation

Validate before calling

function assertMessageId(msg: { messageId?: string }) {
  if (!msg.messageId) {
    throw new Error('messageId is required');
  }
}

Type guard

function hasMessageId(m: unknown): m is { messageId: string } {
  return typeof m === 'object' && m !== null && typeof (m as any).messageId === 'string' && (m as any).messageId.length > 0;
}

Try / catch

try {
  await handleMessage(frame);
} catch (e) {
  if (e instanceof UserError && e.message === 'messageId is required') {
    console.error('Outgoing WS frame missing messageId:', frame);
  } else throw e;
}

Prevention

When it happens

Trigger: Sending a WS request object without a messageId key, an empty string, or undefined value

Common situations: Custom WS clients omitting messageId; copying protocol examples that lacked it; race where subscribe is issued before setting an id.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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