{"record":{"id":"72ac606012737284","repo":"clockworklabs/SpacetimeDB","slug":"v3-websocket-payloads-must-contain-at-least-one-me","errorCode":null,"errorMessage":"v3 websocket payloads must contain at least one message","messagePattern":"v3 websocket payloads must contain at least one message","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"crates/bindings-typescript/src/sdk/websocket_v3_frames.ts","lineNumber":117,"sourceCode":"    ClientMessage.deserialize(reader)\n  );\n}\n\nexport function encodeServerMessagesV3(\n  writer: BinaryWriter,\n  messages: readonly Uint8Array<ArrayBuffer>[]\n): Uint8Array<ArrayBuffer> {\n  return concatenateMessagesV3(writer, messages);\n}\n\nexport function forEachServerMessageV3(\n  reader: BinaryReader,\n  data: Uint8Array,\n  visit: (message: ServerMessage) => void\n): number {\n  reader.reset(data);\n  if (reader.remaining === 0) {\n    throw new RangeError(EMPTY_V3_PAYLOAD_ERR);\n  }\n\n  let count = 0;\n  while (reader.remaining > 0) {\n    visit(ServerMessage.deserialize(reader));\n    count += 1;\n  }\n  return count;\n}\n","sourceCodeStart":99,"sourceCodeEnd":127,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-typescript/src/sdk/websocket_v3_frames.ts#L99-L127","documentation":"SpacetimeDB's v3 WebSocket protocol batches one or more BSATN-encoded server messages into each binary frame. forEachServerMessageV3 refuses to process a frame whose payload is empty (reader.remaining === 0) because a v3 frame must contain at least one message; an empty buffer indicates malformed framing, not a legitimate (empty) batch.","triggerScenarios":"The server (or a custom WebSocketFactory/transport feeding the SDK) delivers a zero-length data frame to the v3 message pump; also reachable when calling forEachServerMessageV3 directly with an empty Uint8Array, e.g. in hand-written tests or a custom transport loop.","commonSituations":"Version skew where a newer host changes framing or emits keepalive/empty frames the SDK doesn't expect; unit tests constructing frames by hand; middleware that drops or splits frame payloads.","solutions":["Align the client SDK and spacetimedb server versions so both implement the same v3 framing","If you pump frames yourself (custom WebSocketFactory or tests), skip zero-length frames instead of passing them to forEachServerMessageV3","Capture raw frames (browser devtools or a logging WebSocketFactory) to identify which side produces the empty payload","If an unmodified server sends empty frames against a matching SDK version, file a bug with the frame capture and host version"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function hasV3Messages(frame: Uint8Array): boolean {\n  return frame.byteLength > 0;\n}\n// in a custom transport/test pump:\nif (!hasV3Messages(frame)) return; // skip empty frame instead of throwing","typeGuard":null,"tryCatchPattern":"In custom transports, wrap forEachServerMessageV3 in try/catch for RangeError, log the frame length, and drop the malformed frame rather than killing the connection.","preventionTips":["Keep SDK and server versions aligned so v3 framing matches","Skip zero-length frames in any custom WebSocketFactory before handing data to the SDK","Add frame-level logging in development to catch malformed batches early"],"tags":["websocket","protocol","serialization","typescript"],"backgroundTag":"invalid-message-frame","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}