h2 breaking changes
Every breaking API change we have recorded in h2 on PyPI: 70 breaking changes in 3 versions. Below are its newest 3 versions, removals and renames first, each with its source.
Newest change August 3, 2026

On this page
4.4.1
- Behavior changed
Requests containing more than one Host header are now rejected. Users who send duplicate Host headers must send a single Host header instead. github.com
4.4.0
- Removed
Python 3.9 is no longer supported, so code running on it must move to a newer Python version. github.com - Removed
PyPy 3.9 is no longer supported, so code running on it must move to a newer PyPy version. github.com - Behavior changed
Non-zero SETTINGS_ENABLE_PUSH values received from servers are now rejected instead of accepted. github.com - Behavior changed
content-length values are now parsed according to the RFC 9110 grammar for numbers (1*DIGIT), which may reject values previously accepted. github.com - Behavior changed
Duplicate content-length headers with conflicting values now raise ProtocolError instead of the first value being silently accepted. github.com - Behavior changed
Ordinary CONNECT requests now require :method=CONNECT and :authority and forbid :scheme and :path; extended CONNECT requires :scheme, :path, :authority and :protocol. github.com - Behavior changed
Stream.end_stream
Stream.end_stream() now raises NoSuchStreamError or StreamClosedError instead of a generic KeyError, so code catching KeyError must catch the new exceptions. github.com - Signature changed
Emitted events are now Python dataclasses with required constructor arguments, so instantiating them without arguments no longer works. github.com - Signature changed
h2.connection.FrameBuffer.add_data
Was def add_data(self, data: bytes) -> None; now def add_data(self, data: Buffer) -> None. pypi.org - Signature changed
h2.connection.H2Connection.receive_data
Was def receive_data(self, data: bytes) -> list[Event]; now def receive_data(self, data: Buffer) -> list[Event]. pypi.org
And 15 more in this version.
4.3.0
- Removed
h2.connection.FrameBuffer.data
FrameBuffer.data was removed in h2 4.3.0 pypi.org - Removed
h2.utilities.UPPER_RE
h2.utilities.UPPER_RE was removed in h2 4.3.0 pypi.org - Behavior changed
Header names and values with characters illegal under RFC 9113 section 8.2.1 are now rejected, so some previously valid requests or responses may be blocked. Use the validate_inbound_headers config option if needed. github.com - Signature changed
h2.connection.InformationalResponseReceived.__init__
Was def __init__(self) -> None; now def __init__(self, stream_id: int, headers: list[Header] = _LAZY_INIT, priority_updated: PriorityUpdated | None = None) -> None. pypi.org - Signature changed
h2.connection.InformationalResponseReceived.headers
Was headers: list[HeaderTuple] | None; now headers: list[Header]. pypi.org - Signature changed
h2.connection.InformationalResponseReceived.stream_id
Was stream_id: int | None; now stream_id: int. pypi.org - Signature changed
h2.connection.PingAckReceived.__init__
Was def __init__(self) -> None; now def __init__(self, ping_data: bytes) -> None. pypi.org - Signature changed
h2.connection.PingAckReceived.ping_data
Was ping_data: bytes | None; now ping_data: bytes. pypi.org - Signature changed
h2.connection.PingReceived.__init__
Was def __init__(self) -> None; now def __init__(self, ping_data: bytes) -> None. pypi.org - Signature changed
h2.connection.PingReceived.ping_data
Was ping_data: bytes | None; now ping_data: bytes. pypi.org
And 34 more in this version.
Check your code
These are the changes. To see which of them reach your code, scan a public repository, or have your coding agent call check_code with your manifest or lockfile over MCP. The API reads every change in every version, not only the newest. On Team and up, a fix pull request opens for the changes that reach a connected repository. Nothing merges or deploys.

Put your code on continuous management.
Scan a public repository now, or give your agent one line.
See how out of date your code is.
Tell your agent what changed since it was trained.
claude mcp add --transport http since https://api.since.dev/mcp