Repository navigation
Http2Stream emit connection related 'error' after receiving all data of stream. #29929
Description
Activity
- addedhttp2Issues and PRs related to the http2 subsystem.Issues and PRs related to the http2 subsystem.streamIssues and PRs related to Node.js streams.Issues and PRs related to Node.js streams.
on Oct 14, 2019 From a purely streams perspective it's fine to emit
'error'as long as'close'has not yet been emitted.@ronag I agree with it.
I just concerned a specific case.
Processing stream could fail by connection related error after a state of the stream closed, which means stream has receivedRST_STREAMand connection related error no longer affects a stream.Maybe the subject of this issue is misleading.
Reacted by Robert Nagy- changed the title
[-]Http2Stream emit 'error' after closed[/-][+]Http2Stream emit connection related 'error' after receiving all data of stream.[/+]on Oct 16, 2019 So the basic issue is that
destroy(err)is unconditionally called on a stream that has been successfully closed by the remote side (in this case RST_STREAM with code 0)?node/lib/internal/http2/core.js
Lines 1066 to 1071 in ff02801
// Destroy any pending and open streams if (state.pendingStreams.size > 0 || state.streams.size > 0) { const cancel = new ERR_HTTP2_STREAM_CANCEL(error); state.pendingStreams.forEach((stream) => stream.destroy(cancel)); state.streams.forEach((stream) => stream.destroy(error)); } Or is it the deferred destroy() when reacting to the
RST_STREAMthat is buggy? Because, if it had already been destroyed, thedestroy(err)from session destruction would never apply.node/lib/internal/http2/core.js
Lines 514 to 534 in ff02801
// Defer destroy we actually emit end. if (!stream.readable || code !== NGHTTP2_NO_ERROR) { // If errored or ended, we can destroy immediately. stream.destroy(); } else { // Wait for end to destroy. stream.on('end', stream[kMaybeDestroy]); // Push a null so the stream can end whenever the client consumes // it completely. stream.push(null); // If the user hasn't tried to consume the stream (and this is a server // session) then just dump the incoming data so that the stream can // be destroyed. if (stream[kSession][kType] === NGHTTP2_SESSION_SERVER && !stream[kState].didRead && stream.readableFlowing === null) stream.resume(); else stream.read(0); } This seems to have been introduced in #18895.
github-actions commented
on Jun 27, 2026 on Jun 27, 2026 – with GitHub ActionsContributorMore actionsThis issue has been marked as stale due to 210 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.- addedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Jun 27, 2026 github-actions commented
on Jul 28, 2026 on Jul 28, 2026 – with GitHub ActionsContributorMore actionsThis issue has been automatically closed after 30 days of inactivity following its stale status (no activity for a total of 120 days).
If this is still relevant, feel free to reopen it or leave a comment with additional details so we can continue the discussion.
The following conditions cause an error event on
http2stream, even thoughhttp2streamreceived all data and RST_STREAM from a client.http2streamis not destroyed(does not consume all data)http2streamreceived all data and RST_STREAMSocket error without goaway frame causes a
http2session.destroy(err).node/lib/internal/http2/core.js
Lines 2678 to 2688 in 81bc7b3
http2session.destroy(err)propagate error tohttp2stream.destroy(err).node/lib/internal/http2/core.js
Lines 1298 to 1323 in 81bc7b3
I thought that
http2streamgot RST_STREAM means that there is no error about processing data. So, I thought ifhttp2streamis closed by RST_STREAM, connection error should not causehttp2streamerror.The codes to reproduce.