java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out) at okhttp3.internal.http2.Http2Connection$ReaderRunnable.onSettings
ID: android/backpressure-queue-overflow-in-okhttp
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| OkHttp 4.12.0 | active | — | — | — |
| Android 14 (API 34) | active | — | — | — |
| Android 13 (API 33) | active | — | — | — |
| OkHttp 3.12.13 | active | — | — | — |
Root Cause
OkHttp's HTTP/2 connection backpressure mechanism triggers a timeout when the server's SETTINGS frame is not acknowledged within the default 2-second window, often due to slow network or server-side connection saturation.
generic中文
OkHttp的HTTP/2连接背压机制在服务器SETTINGS帧未在默认2秒窗口内确认时触发超时,通常是由于网络缓慢或服务器端连接饱和。
Official Documentation
https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/Workarounds
-
75% success Configure OkHttp to use a custom dispatcher with maxRequestsPerHost=1 and retryOnConnectionFailure(true) to reduce backpressure pressure. Example: new OkHttpClient.Builder().dispatcher(new Dispatcher() {{ setMaxRequestsPerHost(1); }}).retryOnConnectionFailure(true).build()
Configure OkHttp to use a custom dispatcher with maxRequestsPerHost=1 and retryOnConnectionFailure(true) to reduce backpressure pressure. Example: new OkHttpClient.Builder().dispatcher(new Dispatcher() {{ setMaxRequestsPerHost(1); }}).retryOnConnectionFailure(true).build() -
85% success Set a custom socket factory that adjusts the SO_TIMEOUT to 5000ms on the underlying socket before the HTTP/2 connection is established. Example: OkHttpClient.Builder().socketFactory(new SocketFactory() { ... });
Set a custom socket factory that adjusts the SO_TIMEOUT to 5000ms on the underlying socket before the HTTP/2 connection is established. Example: OkHttpClient.Builder().socketFactory(new SocketFactory() { ... }); -
90% success Upgrade OkHttp to version 4.12.0 or later which includes a fix for the backpressure timeout handling in the HTTP/2 reader loop.
Upgrade OkHttp to version 4.12.0 or later which includes a fix for the backpressure timeout handling in the HTTP/2 reader loop.
中文步骤
Configure OkHttp to use a custom dispatcher with maxRequestsPerHost=1 and retryOnConnectionFailure(true) to reduce backpressure pressure. Example: new OkHttpClient.Builder().dispatcher(new Dispatcher() {{ setMaxRequestsPerHost(1); }}).retryOnConnectionFailure(true).build()Set a custom socket factory that adjusts the SO_TIMEOUT to 5000ms on the underlying socket before the HTTP/2 connection is established. Example: OkHttpClient.Builder().socketFactory(new SocketFactory() { ... });Upgrade OkHttp to version 4.12.0 or later which includes a fix for the backpressure timeout handling in the HTTP/2 reader loop.
Dead Ends
Common approaches that don't work:
-
Increase OkHttp connectTimeout to 30 seconds
90% fail
connectTimeout controls the initial TCP handshake, not the SETTINGS acknowledgment timeout. The backpressure timeout is hardcoded in OkHttp's HTTP/2 implementation at 2 seconds.
-
Disable HTTP/2 entirely by setting protocol to Protocol.HTTP_1_1
70% fail
While this avoids the error, it disables multiplexing and header compression, degrading performance for all requests. The underlying server or network issue remains unaddressed.
-
Increase readTimeout to 60 seconds
95% fail
readTimeout applies to individual stream reads, not the connection-level SETTINGS exchange. The backpressure timeout is independent and remains at 2 seconds.