{"record":{"id":"0cc4f862008a50b7","repo":"decolua/9router","slug":"aws-eventstream-message-crc-mismatch","errorCode":null,"errorMessage":"AWS EventStream message CRC mismatch","messagePattern":"AWS EventStream message CRC mismatch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"open-sse/executors/kiro.js","lineNumber":1215,"sourceCode":"  if (!(data instanceof Uint8Array) || data.byteLength < 16) {\n    throw new Error(\"AWS EventStream frame is shorter than 16 bytes\");\n  }\n  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n  const totalLength = view.getUint32(0, false);\n  const headersLength = view.getUint32(4, false);\n  if (totalLength !== data.byteLength) {\n    throw new Error(\"AWS EventStream frame length does not match its prelude\");\n  }\n  if (totalLength > EVENTSTREAM_MAX_MESSAGE_BYTES ||\n      headersLength > EVENTSTREAM_MAX_HEADERS_BYTES ||\n      headersLength > totalLength - 16) {\n    throw new Error(\"AWS EventStream frame bounds are invalid\");\n  }\n  if (view.getUint32(8, false) !== crc32(data.subarray(0, 8))) {\n    throw new Error(\"AWS EventStream prelude CRC mismatch\");\n  }\n  if (view.getUint32(totalLength - 4, false) !== crc32(data.subarray(0, totalLength - 4))) {\n    throw new Error(\"AWS EventStream message CRC mismatch\");\n  }\n\n  const headers = Object.create(null);\n  const names = new Set();\n  let offset = 12;\n  const headerEnd = offset + headersLength;\n  const requireBytes = (count) => {\n    if (offset + count > headerEnd) {\n      throw new Error(\"AWS EventStream header exceeds its declared bounds\");\n    }\n  };\n\n  while (offset < headerEnd) {\n    requireBytes(1);\n    const nameLength = data[offset++];\n    requireBytes(nameLength + 1);\n    const name = decoder.decode(data.subarray(offset, offset + nameLength));\n    offset += nameLength;","sourceCodeStart":1197,"sourceCodeEnd":1233,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/open-sse/executors/kiro.js#L1197-L1233","documentation":"Every EventStream frame ends with a CRC32 of the entire message (all bytes except the trailing CRC itself). parseEventFrame() computes crc32(data.subarray(0, totalLength - 4)) and compares it to the last 4 bytes; mismatch means the frame's payload/headers were corrupted after the prelude CRC passed. This is the final integrity gate before headers and JSON payload are decoded.","triggerScenarios":"The recomputed message CRC differs from view.getUint32(totalLength - 4, false): bytes between offset 12 and totalLength-4 were modified in transit, the buffer contents changed between read and parse (reused underlying ArrayBuffer), or the parser is reading a frame assembled from mis-joined chunks.","commonSituations":"Flaky upstream connection or corrupted intermediate hop; a shared/aliased buffer overwritten by a subsequent reader.read() before parsing; a proxy re-encoding (e.g. gzipping) the binary body; desynced multi-frame parsing where chunk boundaries were stitched incorrectly.","solutions":["Copy each complete frame out of the read buffer (slice, not subarray) before parsing so later reads cannot mutate it.","Retry the request — corruption is usually transient transport damage.","Bypass transforming proxies (compression/rewriting layers) for the Kiro EventStream endpoint.","Drop and resynchronize the stream after a bad frame instead of continuing (the executor already cancels the reader on invalid frames — keep that behavior).","Update Node/undici/9router if the corruption reproduces on every request (possible SDK streaming bug)."],"exampleFix":"// before: parse deferred while buffer stays shared with the reader\npendingFrames.push(chunk.subarray(start, end));\n// ...later, after more reads...\nparseEventFrame(pendingFrames[0]); // bytes may already be overwritten\n\n// after: parse or copy immediately\nconst frame = chunk.slice(start, end);\nparseEventFrame(frame);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const { headers, payload } = parseEventFrame(frame);\n  handleFrame(headers, payload);\n} catch (e) {\n  if (e.message.includes('message CRC mismatch')) {\n    log.warn('kiro: frame payload corrupted, aborting stream');\n    await reader.cancel('invalid Kiro EventStream');\n    await retryWithBackoff();\n  } else throw e;\n}","preventionTips":["Parse each complete frame immediately after assembly, or copy it — never let the reader reuse the underlying ArrayBuffer first.","Disable body-transforming middlewares (compression, rewriting) on the EventStream path.","On mismatch, cancel the upstream reader and retry — the executor's existing cancel-then-break pattern is correct.","If every request fails message CRC, suspect the Node/undici streaming layer or a middlebox and test from another network."],"tags":["eventstream","binary-protocol","crc","data-corruption","kiro"],"backgroundTag":"eventstream-crc-mismatch","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}