{"record":{"id":"11f06abfe455d283","repo":"cube-js/cube","slug":"messageid-is-required","errorCode":null,"errorMessage":"messageId is required","messagePattern":"messageId is required","errorType":"validation","errorClass":"UserError","httpStatus":null,"severity":"error","filePath":"packages/cubejs-api-gateway/src/ws/subscription-server.ts","lineNumber":137,"sourceCode":"\n        const acceptanceResult = await this.contextAcceptor(authContext);\n        if (!acceptanceResult.accepted) {\n          this.sendMessage(connectionId, acceptanceResult.rejectMessage);\n          return;\n        }\n\n        await this.subscriptionStore.setAuthContext(connectionId, authContext);\n        this.sendMessage(connectionId, { handshake: true });\n        return;\n      }\n\n      if ('unsubscribe' in message) {\n        await this.subscriptionStore.unsubscribe(connectionId, message.unsubscribe);\n        return;\n      }\n\n      if (!message.messageId) {\n        throw new UserError('messageId is required');\n      }\n\n      authContext = await this.subscriptionStore.getAuthContext(connectionId);\n      if (!authContext) {\n        await this.sendMessage(\n          connectionId,\n          {\n            messageId: message.messageId,\n            message: { error: 'Not authorized' },\n            status: 403\n          }\n        );\n        return;\n      }\n\n      if (!message.method) {\n        throw new UserError('Method is required');\n      }","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-api-gateway/src/ws/subscription-server.ts#L119-L155","documentation":"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.","triggerScenarios":"Sending a WS request object without a messageId key, an empty string, or undefined value","commonSituations":"Custom WS clients omitting messageId; copying protocol examples that lacked it; race where subscribe is issued before setting an id.","solutions":["Include a unique messageId string in every subscription message sent over the WebSocket.","Check that the client SDK serializes the message correctly and does not drop messageId."],"exampleFix":"// before\nsocket.send(JSON.stringify({ method: 'load', query }));\n// after\nsocket.send(JSON.stringify({ messageId: 'q-1', method: 'load', query }));","handlingStrategy":"validation","validationCode":"function assertMessageId(msg: { messageId?: string }) {\n  if (!msg.messageId) {\n    throw new Error('messageId is required');\n  }\n}","typeGuard":"function hasMessageId(m: unknown): m is { messageId: string } {\n  return typeof m === 'object' && m !== null && typeof (m as any).messageId === 'string' && (m as any).messageId.length > 0;\n}","tryCatchPattern":"try {\n  await handleMessage(frame);\n} catch (e) {\n  if (e instanceof UserError && e.message === 'messageId is required') {\n    console.error('Outgoing WS frame missing messageId:', frame);\n  } else throw e;\n}","preventionTips":["Attach a unique messageId to every WS request before sending.","Reuse the same messageId when unsubscribing from a subscription.","Rely on WebSocketTransport, which generates message ids automatically.","Add a serialization helper that enforces messageId presence for all frames."],"tags":["websocket","validation","subscription","protocol"],"backgroundTag":"missing-required-argument","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}