diff --git a/.changesets/maint_jc_bump_h2_min_version.md b/.changesets/maint_jc_bump_h2_min_version.md new file mode 100644 index 0000000000..05769d3075 --- /dev/null +++ b/.changesets/maint_jc_bump_h2_min_version.md @@ -0,0 +1,11 @@ +### Pin transitive `h2` dependency at minimum v0.4.13 to pick up critical flow-control, deadlock, and tracing fixes ([PR #9033](https://github.com/apollographql/router/pull/9033)) + +`h2` 0.4.13 (released January 5, 2026) contains three fixes directly relevant to the router, which uses h2 exclusively as a client when connecting to subgraphs: + +- **Capacity deadlock under concurrent streams ([#860](https://github.com/hyperium/h2/pull/860)) — high relevance:** Under concurrent load with `max_concurrent_streams` limits in effect, flow-control capacity could be assigned to streams still in `pending_open` state. Those streams could never consume the capacity, starving already-open streams and permanently freezing all outgoing traffic on the connection with no error surfaced. This is directly triggerable in the router: any subgraph behind Envoy or a gRPC backend advertises a `max_concurrent_streams` limit (Envoy defaults to 100), and under production load the router will routinely queue more concurrent requests than that limit allows. + +- **OTel tracing span lifetime leak ([#868](https://github.com/hyperium/h2/pull/868)) — high relevance:** The h2 `Connection` object captured the active tracing span at connection creation time as its parent, keeping that span alive for the entire lifetime of the connection. Since the router wraps every subgraph request in an OpenTelemetry span and connections are pooled, affected spans could linger indefinitely under sustained traffic — never being exported to the tracing backend and accumulating in memory. + +- **Flow-control stall on padded DATA frames ([#869](https://github.com/hyperium/h2/pull/869)) — lower relevance for typical subgraphs, higher for connectors:** Padding bytes in `DATA` frames were not being returned to the flow-control window, causing the connection window to drain to zero and permanently stalling downloads with no error. Typical GraphQL/gRPC subgraphs do not send padded frames, but router connectors calling arbitrary HTTP APIs (e.g., Google Cloud Storage or CDN-backed endpoints) can encounter this. + +By [@theJC](https://github.com/theJC) in https://github.com/apollographql/router/pull/9033 diff --git a/Cargo.lock b/Cargo.lock index 9aee00ce8f..1d82b39402 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -332,6 +332,7 @@ dependencies = [ "futures", "futures-test", "graphql_client", + "h2", "heck 0.5.0", "hex", "hickory-resolver", @@ -2091,7 +2092,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.0", + "windows-sys 0.60.2", ] [[package]] @@ -2926,9 +2927,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -3294,7 +3295,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -3566,7 +3567,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -4188,7 +4189,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.60.2", ] [[package]] @@ -5195,7 +5196,7 @@ dependencies = [ "once_cell", "socket2 0.5.10", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -5809,7 +5810,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.0", + "windows-sys 0.52.0", ] [[package]] @@ -6502,7 +6503,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.0", + "windows-sys 0.52.0", ] [[package]] diff --git a/apollo-router/Cargo.toml b/apollo-router/Cargo.toml index 5f7e57a816..2f2b1cc286 100644 --- a/apollo-router/Cargo.toml +++ b/apollo-router/Cargo.toml @@ -106,6 +106,9 @@ fred = { version = "10.1.0", features = [ socket2 = { version = "0.5", features = ["all"] } futures = { version = "0.3.30", features = ["thread-pool"] } graphql_client = "0.14.0" +# Not used directly, but declared here to enforce a minimum version floor for this +# transitive dependency and to allow Renovate to manage future version bumps. +h2 = "0.4.13" hex.workspace = true http.workspace = true http-body = "1.0.1"