Skip to content

[dd-sdk-android-okhttp 3.9.0] DatadogInterceptor deadlocks SSE / long-lived streaming responses #3407

Description

@waliahimanshu

Describe the bug

Summary

Upgrading com.datadoghq:dd-sdk-android-okhttp from 3.8.0 → 3.9.0 breaks
GraphQL subscriptions delivered over Server-Sent Events (SSE). On 3.9.0, the
DatadogInterceptor appears to read/await the entire response body before
returning, which never completes for an unbounded SSE stream — OkHttp Call.execute()
never resumes, so the SSE consumer (Apollo Kotlin's SseNetworkTransport in our case)
never starts parsing events.

3.8.0 with the same OkHttp interceptor stack works correctly: Call.execute()
returns on response headers and the streaming body is read incrementally.

Affected versions

  • Broken: com.datadoghq:dd-sdk-android-okhttp:3.9.0
  • Working: com.datadoghq:dd-sdk-android-okhttp:3.8.0

Environment

  • Android compileSdk 35, minSdk 26
  • Kotlin 2.x
  • OkHttp (transitive via Datadog/Apollo, default version)
  • Apollo Kotlin 4.4.3 with a custom SseNetworkTransport that wraps OkHttp via
    Apollo's DefaultHttpEngine (uses synchronous call.execute() per
    dd-sdk-android-gradle-plugin users will recognize)

Reproduction

  1. Build an OkHttpClient with DatadogInterceptor registered as an
    application interceptor:
    OkHttpClient.Builder()                                                                                                                                                                                                             
      .addInterceptor(datadogInterceptor)                                                                                                                                                                                              
      .readTimeout(0, TimeUnit.MILLISECONDS) // long-lived stream                                                                                                                                                                      
      .build()                                                                                                                                                                                                                         
                                                                                                   

Content-Type: text/event-stream and keeps the connection open
indefinitely (e.g. a graphql-sse subscription endpoint).
3. The server returns 200 OK and starts pushing
event: next\ndata: {...}\n\n chunks at ~1 Hz.
4. Observed on 3.9.0: OkHttp's Call.execute() does not return; the
client never reads any response body bytes. The connection sits idle
from the consumer's perspective even as the server is actively pushing.
5. Observed on 3.8.0: Call.execute() returns immediately on response
headers. Each pushed event is consumed and parsed.

What we ruled out

  • Apollo / our own SSE transport: identical between 3.8.0 and 3.9.0 runs.
  • Server: identical responses verified via a second client (web).
  • OkHttp version: unchanged across the bump.
  • Other interceptors in the stack (auth, tracing network interceptor, app
    version header) — unchanged across the bump.

Workaround we applied

Strip DatadogInterceptor from the OkHttpClient used for SSE only:

authenticatedOkHttpClient.newBuilder()
.readTimeout(0, TimeUnit.MILLISECONDS)
.also { builder ->
builder.interceptors().removeAll { it is DatadogInterceptor }
}
.build()

This loses the per-request DatadogInterceptor reporting (RUM resource
tracking) for the streaming request, which would be inaccurate for SSE
anyway. The network-layer TracingInterceptor and DatadogEventListener
are kept and continue to report APM spans / connection events.

Reproduction steps

Test SSE events real time subscription.

Logcat logs

No response

Expected behavior

SSE events do not break with using datadog interceptor

Affected SDK versions

3.8.0

Latest working SDK version

3.8.0

Did you confirm if the latest SDK version fixes the bug?

No

Kotlin / Java version

No response

Gradle / AGP version

No response

Other dependencies versions

No response

Device Information

No response

Other relevant information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions