Skip to content

fix(h2): preserve accepted streams with deferred ids - #6090

Merged
mcollina merged 1 commit into
nodejs:mainfrom
EpicHigh:fix/h2-deferred-stream-id
Oct 29, 2026
Merged

mcollina merged 1 commit into
nodejs:mainfrom
EpicHigh:fix/h2-deferred-stream-id

Conversation

@EpicHigh

Copy link
Copy Markdown
Contributor

This relates to...

Fixes #6089

Rationale

bindRequestToStream() caches stream.id before a pending stream has necessarily received an ID. When GOAWAY later includes that stream's assigned ID, the cached undefined makes Undici reject an accepted response.

Read the live stream ID when GOAWAY arrives. This follows the existing Http2Stream.id contract without adding runtime-specific behavior.

Changes

Bug Fixes

  • Use the current stream ID to decide which requests GOAWAY accepted, and remove the cached ID.
  • Add GET and streamed-POST regressions over real HTTP/2 connections. The Node fixture delays ID visibility until the next microtask; each response must finish exactly once, and a subsequent request must use a new connection.
  • Update existing cleanup and replay fixtures to use the retained stream reference.

Features

N/A

Breaking Changes and Deprecations

None.

Validation

  • Both new regression tests fail on main 046bb4c6 with UND_ERR_INFO and pass with this change.
  • npm run test:h2: 147 core tests and 14 Fetch tests pass on Node v24.22.1.
  • npm run lint passes.
  • Standalone GET and streamed-POST checks against a separate Node HTTP/2 server pass on Node v24.22.1 and Bun 1.4.4. Before the change, both Bun cases fail after receiving status 200.
  • The standalone reproduction in HTTP/2: GOAWAY rejects accepted streams whose IDs were assigned asynchronouslyΒ #6089 also passes on both runtimes.

The full repository test suite and other operating systems were not run.

Status

  • I have read and agreed to the Developer's Certificate of Origin
  • Tested
  • [S] Benchmarked (error handling path)
  • [S] Documented (no public API change)
  • Review ready
  • In review
  • Merge ready

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@codecov-commenter

codecov-commenter commented Oct 25, 2026 •

Copy link
Copy Markdown

Codecov Report

βœ… All modified and coverable lines are covered by tests.
βœ… Project coverage is 91.60%. Comparing base (046bb4c) to head (47520d6).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6090      +/-   ##
==========================================
- Coverage   91.61%   91.60%   -0.01%     
==========================================
  Files         113      113              
  Lines       44044    44043       -1     
==========================================
- Hits        40351    40346       -5     
- Misses       3693     3697       +4     

β˜” View full report in Codecov by Harness.
πŸ“’ Have feedback on the report? Share it here.

πŸš€ New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • πŸ“¦ JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mcollina
mcollina merged commit 1b7b18e into nodejs:main Oct 29, 2026
38 checks passed
@EpicHigh
EpicHigh deleted the fix/h2-deferred-stream-id branch October 31, 2026 10:04
@github-actions github-actions Bot mentioned this pull request Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTTP/2: GOAWAY rejects accepted streams whose IDs were assigned asynchronously

3 participants