{"record":{"id":"adebc50d75102882","repo":"cube-js/cube","slug":"method-is-required","errorCode":null,"errorMessage":"Method is required","messagePattern":"Method is required","errorType":"validation","errorClass":"UserError","httpStatus":null,"severity":"warning","filePath":"packages/cubejs-api-gateway/src/ws/subscription-server.ts","lineNumber":154,"sourceCode":"      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      }\n\n      if (!methodParams.hasOwnProperty(message.method)) {\n        throw new UserError(`Unsupported method: ${message.method}`);\n      }\n\n      const subscriptionId = message.messageId;\n      const baseRequestId = message.requestId || `${connectionId}-${subscriptionId}`;\n      const requestId = `${baseRequestId}-span-${uuidv4()}`;\n\n      context = await this.apiGateway.contextByReq(\n        // TODO: We need to standardize type for WS request type\n        message as any,\n        authContext.securityContext,\n        requestId\n      );\n\n      this.apiGateway.log({","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-api-gateway/src/ws/subscription-server.ts#L136-L172","documentation":"The WebSocket subscription server validates every incoming message before dispatching it to a registered method. A message without a `method` field cannot be routed, so handleMessage throws UserError('Method is required') before any handler lookup. This is an input-validation error sent back to the WS client rather than a server crash.","triggerScenarios":"Client sends a JSON WS message lacking the `method` property, e.g. `{ messageId: '1', params: {...} }`, via the subscription transport.","commonSituations":"Hand-rolled WebSocket clients, custom frontends not using @cubejs-client/ws, typos like `Method`, or messages that only carry a payload without specifying which API method to invoke.","solutions":["Add a `method` field to the WS message (e.g. { method: 'load', ... }) matching a key in methodParams","Verify the client uses the official Cube WebSocket transport which always sets `method`","Log the raw incoming message on the client to confirm what is actually serialized"],"exampleFix":"// before\nsocket.send(JSON.stringify({ messageId: '1', query }))\n// after\nsocket.send(JSON.stringify({ messageId: '1', method: 'load', params: { query } }))","handlingStrategy":"validation","validationCode":"function sendWsMessage(socket, msg) {\n  if (typeof msg.method !== 'string' || !msg.method) throw new TypeError('WS message requires a method field')\n  socket.send(JSON.stringify(msg))\n}","typeGuard":"function hasMethod(m: unknown): m is { method: string } {\n  return !!m && typeof m === 'object' && typeof (m as any).method === 'string' && (m as any).method.length > 0\n}","tryCatchPattern":"socket.on('message', raw => {\n  const msg = JSON.parse(raw)\n  if (!msg.method) return console.error('Cube WS: method field is required in', msg)\n  // dispatch\n})","preventionTips":["Always build WS messages via the official Cube client transport instead of hand-rolling JSON","Add a unit test asserting every outgoing message includes `method`","Log outgoing payloads when debugging the subscription protocol"],"tags":["websocket","validation","protocol"],"backgroundTag":"missing-request-field","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}