android network_error ai_generated true

java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out) at okhttp3.internal.http2.Http2Connection$ReaderRunnable.onSettings

ID: android/backpressure-queue-overflow-in-okhttp

Also available as: JSON · Markdown · 中文
82%Fix Rate
85%Confidence
1Evidence
2023-06-15First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
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

  1. 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()
  2. 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() { ... });
  3. 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.

中文步骤

  1. 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()
  2. 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() { ... });
  3. 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:

  1. 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.

  2. 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.

  3. 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.