Skip to content

UnsupportedOperationException: third-party implementation of CancellableContinuation when using Kotlin coroutines with New Relic Java agent #2581

@JeHuiPark

Description

@JeHuiPark

Description

When running a Kotlin coroutine–based application with the New Relic Java agent (v8.25.0) attached, the process throws an exception inside a coroutine delay() call:

java.lang.UnsupportedOperationException: third-party implementation of CancellableContinuation is not supported
    at kotlinx.coroutines.CancellableContinuationKt.invokeOnCancellation(CancellableContinuation.kt:240)
    at kotlinx.coroutines.CancellableContinuationKt.disposeOnCancellation(CancellableContinuation.kt:417)
    at kotlinx.coroutines.EventLoopImplBase.scheduleResumeAfterDelay(EventLoop.common.kt:238)
    at kotlinx.coroutines.DelayKt.delay(Delay.kt:126)
    ...

The exception occurs only when the agent is active (-javaagent:/newrelic/newrelic-agent.jar).
If the agent is removed, the coroutine executes normally without any errors.

It seems that the agent’s bytecode instrumentation wraps or modifies the coroutine continuation classes, causing the kotlinx.coroutines runtime to detect a “third-party implementation” and throw this UnsupportedOperationException.

Expected Behavior

Coroutines should operate normally with the New Relic Java agent attached.

Troubleshooting or NR Diag results

Relevant log excerpt:

Picked up JAVA_TOOL_OPTIONS: -javaagent:/newrelic/newrelic-agent.jar ...
com.newrelic INFO: Using default collector host: collector.newrelic.com
Exception in thread "DefaultDispatcher-worker-1" java.lang.UnsupportedOperationException:
third-party implementation of CancellableContinuation is not supported

When the same build runs without the agent, this exception does not appear.

Steps to Reproduce

  1. Create a minimal Kotlin application with kotlinx-coroutines-core:1.9.0.
  2. Add the following coroutine code:
    CoroutineScope(ctx).launch {
        // some work
        delay(intervalTime)
        // some work
    }
  3. Start the JVM with:
    -javaagent:/newrelic/newrelic-agent.jar
    
  4. Observe that the application fails with UnsupportedOperationException during the first delay() call.

Your Environment

  • kotlinx-coroutines-core: 1.9.0
  • New Relic Java agent: 8.25.0
  • JVM: OpenJDK 17 (Adoptium 17.0.17)
  • Framework: Spring Boot 3.3.x (Netty-based reactive runtime)
  • Runtime: eclipse-temurin:17-jre-alpine
  • Command line:
    -javaagent:/newrelic/newrelic-agent.jar
    

Additional context

This appears to originate from a defensive check inside kotlinx.coroutines.CancellableContinuationKt.invokeOnCancellation(),
which throws when the continuation is not a CancellableContinuationImpl.

That method is defined here in Kotlin’s source:
https://github.com/Kotlin/kotlinx.coroutines/blob/5d4954b17ac18c572e22a9a6e7bb4e4368ec568c/kotlinx-coroutines-core/common/src/CancellableContinuation.kt#L309-L316

The issue seems related to instrumentation changes introduced around #2454

Workaround:
Downgrading the New Relic Java agent from 8.25.0 to 8.24.0 resolves the issue.
With version 8.24.0, coroutine delay() and other suspension functions operate normally.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working as designed/intended

    Type

    No type

    Projects

    Status

    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions