Conversation
Next.js <=16.3.x (incl. 16.3.4 and latest stable 16.3.5) leaks one `drain` listener per backpressured write onto the vendored compression middleware's Gzip stream when piping App Router HTML/RSC responses, producing "MaxListenersExceededWarning: 11 drain listeners added to [Gzip]" (vercel/next.js#97698; upstream compression PR expressjs/compression#153 has been open since 2019). The fix only ships in 16.4.0-canary.10+. Since the dashboard is served over loopback/LAN where gzip gains nothing, set `compress: false` — this removes the Gzip stream entirely instead of masking the warning with setMaxListeners.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
Windows(以及其他平台)上运行
agentboard serve,浏览器首次加载 dashboard 后终端反复出现:根因(Next.js 框架 bug,非本项目代码)
pipeNodeReadableToNodeResponse输出;每当res.write()返回false(gzip 压缩缓冲写满、产生背压),它就执行一次res.once('drain', ...)。compression中间件会把res.on转发到底层 zlibGzip流,但没有转发removeListener(上游缺陷 expressjs/compression#153,2019 年挂起至今,compression 1.8.1 仍未修)。于是这些once监听器挂在 Gzip 流上永远不会被移除——每次背压写泄漏一个,第 11 个触发 Node 的MaxListenersExceededWarning。16.3.4(当前依赖)和最新稳定版16.3.5均带此 bug;官方修复 vercel/next.js#97698(每个响应只挂一个常驻drain监听器)2026-08-24 才合并,首个包含修复的版本是16.4.0-canary.10,尚无稳定版。也就是说:浏览器打开 dashboard 时,流式渲染的 HTML/RSC 响应经过 gzip 压缩产生背压,每写满一次缓冲区就泄漏一个监听器,刷几次页面 warning 就出现几次。
修复
在
next.config.ts设置compress: false:setMaxListeners掩盖症状);验证
本地
npm run build && agentboard serve(或npm run start)后浏览器访问 dashboard,MaxListenersExceededWarning不再出现。