Given that the loggingTransform captures the correct order, the problem is almost certainly after that, i.e. in:
createSSEParserTransform(...)Readable.toWeb(...)new Response(webStream, ...)Readable.fromWeb(...)nodeReadable.pipe(res)
File:
../routstr-chat/sdk/client/sse.ts
It buffers text until it finds an SSE terminator:
buffer += chunk.toString();
while ((match = terminator.exec(buffer)) !== null) {
const block = buffer.slice(lastIndex, match.index);
...
self.push(eventBlock + "\n\n");
}So even if loggingTransform sees correct raw order, the SSE parser is:
- consuming arbitrary upstream chunks
- reconstructing event blocks
- emitting new chunks downstream
That means after the logging stage, the output stream is no longer the original byte stream. It is a rewritten one.
If your client is sensitive to exact chunk timing/boundaries, this is the prime suspect.
Even if event order is technically preserved, downstream may observe:
- one later fragment arriving with an earlier event block
- multiple adjacent SSE events coalesced into one downstream chunk
- boundaries shifted compared to the original upstream stream
That often gets described as “chunks are a bit out of order,” even when the actual issue is: re-buffering + re-emission changes packetization.
Strongest suspect.
Reasons:
- it rewrites the stream
- it buffers
- it emits on event boundaries, not incoming chunk boundaries
- it uses string accumulation and parsing
Second strongest suspect.
The SDK does:
- Node stream → Web stream
- later Web stream → Node stream again
Those adapters can:
- coalesce pushes
- alter flush timing
- change chunk granularity
Usually they shouldn’t reorder data semantically, but they can definitely alter when chunks become visible.
Less likely as a root cause by itself, but if the stream has already been re-chunked, this is where the client sees it.
It uses plain chunk.toString() on arbitrary stream chunks:
buffer += chunk.toString();This is unsafe for UTF-8 boundaries. If a multi-byte character is split across chunks, decoding each chunk independently can produce malformed text or replacement characters, and that can affect:
- SSE field parsing
- JSON parsing
- event boundary reconstruction
That’s not classic “reordering,” but it can absolutely create weird slight stream corruption after the logging stage.
And importantly:
- the logger records the original raw chunk strings as seen before parsing
- the parser then re-decodes / re-buffers them
- so the bug can appear after logging even though the log looks fine
Most likely:
- upstream stream order is correct
loggingTransformconfirms thatcreateSSEParserTransformbuffers/rebuilds the stream- this changes event/chunk emission enough that downstream sees slight ordering/boundary anomalies
If it’s not that, then the next likely culprit is the Node→Web→Node conversion chain.
Primary suspect: ../routstr-chat/sdk/client/sse.ts
Secondary suspect: the Readable.toWeb(...) / Readable.fromWeb(...) roundtrip in RoutstrClient.ts
If you want, I can next walk through the exact downstream path and identify the single narrowest point where bytes stop being identical to what logging saw.