SSE and NDJSON response streams drain unread sources without backpressure
Maintainer thường phản hồi trong vòng 1 ngày
@tombeckenham đang làm issue này rồi.
Từ ngày 28/9/2026.
Đánh giá
Issue này chưa được đánh giá.
Mô tả
TanStack AI version
@tanstack/[email protected]; reproduced on clean main at 62bec34bb.
Framework/Library version
Node.js 24.11.1, native WHATWG ReadableStream; no framework or provider credentials required.
Describe the bug and the steps to reproduce it
toHttpStream() (NDJSON) and toServerSentEventsStream() (SSE) continue consuming their AsyncIterable even when nobody reads the returned response stream. toEncodedStream() starts its pump in ReadableStream.start() (packages/ai/src/stream-to-response.ts:167-175 on the commit above), then calls iterator.next() and controller.enqueue() repeatedly (:176-186) without checking controller.desiredSize. The default stream queue therefore does not limit source consumption. A stalled HTTP reader can accumulate the complete response in memory.
From the repository root, save this as repro-backpressure.mts and run pnpm exec tsx repro-backpressure.mts:
import {
toHttpStream,
toServerSentEventsStream,
} from './packages/ai/src/stream-to-response.ts'
for (const [name, encode] of [
['SSE', toServerSentEventsStream],
['NDJSON', toHttpStream],
] as const) {
let produced = 0
async function* source() {
for (let i = 0; i < 10_000; i++) {
produced++
yield {
type: 'TEXT_MESSAGE_CONTENT' as const,
messageId: 'm',
timestamp: Date.now(),
delta: 'x',
}
}
}
const response = encode(source())
await new Promise((resolve) => setTimeout(resolve, 50))
console.log(`${name}: pulled ${produced} chunks without a reader`)
await response.cancel()
if (produced !== 1) process.exitCode = 1
}
Actual on clean main: both formats drain the source despite having no reader:
SSE: pulled 10000 chunks without a reader
NDJSON: pulled 10000 chunks without a reader
exit 1
Expected: one chunk may occupy the default queue. The producer should pause until a reader consumes that chunk. Running the same probe on the proposed fix prints SSE: pulled 1 chunks without a reader and NDJSON: pulled 1 chunks without a reader, exit 0.
The source-level regression test also checks that reading one chunk resumes production, that cancellation cleans up the source, and that an error from a paused source reaches the reader. It is on the proposed branch.
Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
Runnable repository regression test. The complete standalone probe is inline above; it uses only the source checkout and Node's native streams.
User impact
An endpoint that hands a long or fast model output to either helper can keep requesting provider chunks after its downstream client stalls. Memory use then grows with the entire response instead of with the stream's queue. This is especially relevant to long-running responses and clients on slow connections.
Scope and existing reports
Searched repository Issues and PRs for backpressure, slow client, unbounded stream, buffering stream, and response stream on 2026-09-28; found no report of this SSE/NDJSON response-queue behavior. PR #1541 concerns generated-media upload streaming; PR #969 concerns WebSocket transport. Neither addresses this encoder.
Do you intend to try to help solve this bug with your own PR?
Yes. A separate PR will link this issue.
Screenshots or Videos (Optional)
Not applicable; the producer count is asserted directly.
Terms & Code of Conduct
- I agree to follow this project's Code of Conduct.
- I understand that a bug without a reliable reproduction can be closed.
- Ngôn ngữ chính
- TypeScript
- Star
- 3.1k
- Fork
- 340
- Merge trung bình
- 2 ngày 10 giờ
- Pull request đã merge (30 ngày)
- 169
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của TanStack/ai
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 38/100
Maintainer thường phản hồi trong vòng 1 ngày
-
withPersistence re-appends stored tool results on an interrupt resume (snapshot ids never match stored id-less tool messages)Có thể đã có người làm @tombeckenham đã nhận hôm nay. Đang mởwaiting-on: maintainer
TanStack/ai#1580 · 1 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
signin with openaiĐang mởhas-pr waiting-on: maintainer
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 45/100
TanStack/ai#1572 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
update elevenlabsCó thể đã có người làm @tombeckenham đã nhận 2 ngày trước. Đang mởhas-pr waiting-on: maintainer
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 25/100
TanStack/ai#1564 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Issue tương tự
-
area/frontend good first issue kind/cooldown
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
voidzero-dev/oxc-angular-compiler#511 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
langchain-ai/deepagentsjs#898 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 92/100
anomalyco/models.dev#8509 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug documentation P2 UI/UX
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 1 ngày