Skip to content

Deliver a promised stream's response HEADERS received after GOAWAY#192

Open
const86 wants to merge 1 commit into
igrigorik:mainfrom
const86:fix/goaway-promised-stream-response
Open

Deliver a promised stream's response HEADERS received after GOAWAY#192
const86 wants to merge 1 commit into
igrigorik:mainfrom
const86:fix/goaway-promised-stream-response

Conversation

@const86

@const86 const86 commented Jul 9, 2026

Copy link
Copy Markdown

On receiving GOAWAY the connection moves to :closed, after which #receive dropped every inbound HEADERS frame - including the response HEADERS of a stream the peer promised to finish (id <= last_stream_id). That stream's DATA frames were still delivered (the DATA branch has no :closed guard), so the consumer saw a malformed, headerless response and the request was lost.

RFC 9113 Section 6.8 says a receiver of GOAWAY may still complete streams at or below last_stream_id. Only discard HEADERS that would open a NEW stream (id not already in @streams); keep delivering an in-flight stream's response.

This bites whenever a server emits GOAWAY just ahead of the response on the same connection - e.g. golang.org/x/net/http2 graceful shutdown - which loses responses the server actually processed and put on the wire.

On receiving GOAWAY the connection moves to :closed, after which #receive
dropped every inbound HEADERS frame - including the response HEADERS of a
stream the peer promised to finish (id <= last_stream_id). That stream's
DATA frames were still delivered (the DATA branch has no :closed guard), so
the consumer saw a malformed, headerless response and the request was lost.

RFC 9113 Section 6.8 says a receiver of GOAWAY may still complete streams at
or below last_stream_id. Only discard HEADERS that would open a NEW stream
(id not already in @streams); keep delivering an in-flight stream's response.

This bites whenever a server emits GOAWAY just ahead of the response on the
same connection - e.g. golang.org/x/net/http2 graceful shutdown - which
loses responses the server actually processed and put on the wire.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant