{"record":{"id":"8caca555a0ffcaae","repo":"cube-js/cube","slug":"invalid-unsubscribe-message-format","errorCode":null,"errorMessage":"Invalid unsubscribe message format","messagePattern":"Invalid unsubscribe message format","errorType":"validation","errorClass":"CubejsHandlerError","httpStatus":400,"severity":"error","filePath":"packages/cubejs-api-gateway/src/ws/subscription-server.ts","lineNumber":78,"sourceCode":"    return error.issues\n      .map(e => (e.path.length ? `${e.path.join('.')}: ${e.message}` : e.message))\n      .join(', ');\n  }\n\n  protected validateMessage(message: object): WsMessage {\n    if ('authorization' in message) {\n      const result = authMessageSchema.safeParse(message);\n      if (!result.success) {\n        throw new CubejsHandlerError(400, 'Invalid authorization message format', this.mapZodError(result.error));\n      }\n\n      return result.data;\n    }\n\n    if ('unsubscribe' in message) {\n      const result = unsubscribeMessageSchema.safeParse(message);\n      if (!result.success) {\n        throw new CubejsHandlerError(400, 'Invalid unsubscribe message format', this.mapZodError(result.error));\n      }\n\n      return result.data;\n    }\n\n    const result = methodMessageSchema.safeParse(message);\n    if (!result.success) {\n      throw new CubejsHandlerError(400, 'Invalid message format', this.mapZodError(result.error));\n    }\n\n    return result.data;\n  }\n\n  public async processMessage(connectionId: string, body: string) {\n    let message: any | undefined;\n\n    try {\n      message = this.deserializeMessage(body);","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-api-gateway/src/ws/subscription-server.ts#L60-L96","documentation":"A WebSocket message containing an 'unsubscribe' property is validated against unsubscribeMessageSchema (expecting the correct key/id per schema). Zod validation failure throws CubejsHandlerError(400, 'Invalid unsubscribe message format') with a field-level detail.","triggerScenarios":"Sending { unsubscribe: ... } with a missing, misnamed, or wrong-typed value — e.g. { unsubscribe: 123 } when a string subscription id is required, or embedding extra required-incompatible fields.","commonSituations":"Hand-rolled clients guessing the unsubscribe protocol; storing numeric subscription ids from a different API and sending them; client/server version mismatch after an upgrade of the WS protocol schema.","solutions":["Send the exact shape unsubscribeMessageSchema requires (typically { messageId, unsubscribe: '<subscriptionId>' } with a string id).","Use the error's Zod detail (field path and message) to correct the offending property.","Switch to the official WebSocketTransport/subscribe() API so unsubscribe frames are built for you."],"exampleFix":"// before\nsocket.send(JSON.stringify({ unsubscribe: 42 }));\n// after\nsocket.send(JSON.stringify({ messageId: '3', unsubscribe: '42' }));","handlingStrategy":"validation","validationCode":"function isValidUnsubscribeMessage(msg: unknown): boolean {\n  const m = msg as any;\n  return typeof m === 'object' && m !== null &&\n    typeof m.messageId === 'string' &&\n    typeof m.unsubscribe === 'string';\n}","typeGuard":"function isUnsubscribeMessage(m: unknown): m is { messageId: string, unsubscribe: string } {\n  return typeof m === 'object' && m !== null && 'unsubscribe' in m &&\n    typeof (m as any).unsubscribe === 'string';\n}","tryCatchPattern":"try {\n  await handleMessage(frame);\n} catch (e) {\n  if (e.status === 400 && e.error === 'Invalid unsubscribe message format') {\n    console.error('Unsubscribe frame rejected:', e.message);\n  } else throw e;\n}","preventionTips":["Send unsubscribe as a string subscription id paired with the same messageId used at subscribe time.","Store subscription ids as strings end-to-end.","Use the official client's unsubscribe() rather than raw frames.","Confirm the schema shape against your server version when upgrading."],"tags":["websocket","validation","zod","subscription"],"backgroundTag":"invalid-message-format","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}