STREAM_CLOSED
STREAM_CLOSED (0x5) is sent when a frame is received for a stream that is already in the closed state. HTTP/2 streams go through a defined lifecycle – once closed, receiving further frames on that stream ID is a protocol error. The receiving endpoint sends RST_STREAM with STREAM_CLOSED.
Code
0x5
Decimal
5
Standard
RFC 9113 §7
Description
HTTP/2 streams have a well-defined state machine: idle → open → half-closed (local/remote) → closed. Once a stream is closed, any DATA, HEADERS, PUSH_PROMISE, or CONTINUATION frame received on that stream ID triggers STREAM_CLOSED. This is a stream-level error – the connection remains open. The peer may have a race condition where it sent frames before receiving the RST_STREAM or END_STREAM that closed the stream. Implementations must handle STREAM_CLOSED gracefully in concurrent environments.
Common Causes
- –DATA frame received on a stream already closed
- –Race condition: peer sent frames before receiving END_STREAM
- –Server sent RST_STREAM but client continued sending DATA
- –Implementation bug tracking stream state incorrectly