You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
http2: large queued request body prevents receiving an early response #66739
Darwin miki.local 25.6.0 Darwin Kernel Version 25.6.0: Sat Jul 11 15:27:04 PDT 2026; root:xnu-12377.161.13~4/RELEASE_ARM64_T6050 arm64
Subsystem
http2
What steps will reproduce the bug?
Save the following code into a file and run it. For the 16MB request with the default session limit, node reports ERR_HTTP2_STREAM_ERROR: Stream closed with error code NGHTTP2_ENHANCE_YOUR_CALM rather than the 413.
// A client that queues a large request body cannot read an early response.// Cleartext HTTP/2 (h2c), no dependencies: `node repro.mjs`.importhttp2from'node:http2';constserver=http2.createServer();constsessions=newSet();server.on('session',(session)=>sessions.add(session));server.on('stream',(stream)=>{stream.on('error',()=>{});// the client may reset the stream// Reject without reading the request body, as a server does for a 401 or 413.stream.respond({':status': 413});stream.end('payload too large');});awaitnewPromise((resolve)=>server.listen(0,resolve));constorigin=`http://localhost:${server.address().port}`;constpost=(bodyBytes,sessionOptions={})=>newPromise((resolve)=>{constsession=http2.connect(origin,sessionOptions);constreq=session.request({':method': 'POST',':path': '/'});req.on('response',(headers)=>resolve(`status ${headers[':status']}`));req.on('error',(err)=>resolve(`${err.code}: ${err.message}`));req.on('close',()=>session.destroy());req.end(Buffer.alloc(bodyBytes));// the whole body in one write});constMiB=1024*1024;console.log(`node ${process.version}`);console.log(' 8 MiB body: ',awaitpost(8*MiB));console.log('16 MiB body: ',awaitpost(16*MiB));console.log('16 MiB, maxSessionMemory 64 MB:',awaitpost(16*MiB,{maxSessionMemory: 64}));for(constsessionofsessions)session.destroy();server.close();
How often does it reproduce? Is there a required condition?
To reproduce, more than maxSessionMemory worth of request-body data must be queued when the response arrives.
What is the expected behavior? Why is that the expected behavior?
I'd expect consistent propagation of the server's 413 responses
What do you see instead?
Opaque stream error (ERR_HTTP2_STREAM_ERROR: Stream closed with error code NGHTTP2_ENHANCE_YOUR_CALM) and no response
Activity
inoway46 commentedon Oct 15, 2026
Reproduced with a local main build (macOS x64, 38aa1f3), which reports
NGHTTP2_INTERNAL_ERROR.Queued outbound data exceeds the session memory limit, so
AddHeader()rejects response headers. The reset is deferred during receive processing, and nghttp2 queuesINTERNAL_ERRORfor the callback failure.On this build, increasing
maxSessionMemoryto 64 or streaming with backpressure allows the 413 response through without errors.@nodejs/http2 Could you clarify whether this limit should prevent receiving response headers on an existing stream?