Skip to content

馃挜 Support Kotlin 2.4 async method references - #3111

Open
Quinn-With-Two-Ns wants to merge 2 commits into
temporalio:mainfrom
Quinn-With-Two-Ns:issue-2989
Open

Quinn-With-Two-Ns wants to merge 2 commits into
temporalio:mainfrom
Quinn-With-Two-Ns:issue-2989

Conversation

@Quinn-With-Two-Ns

@Quinn-With-Two-Ns Quinn-With-Two-Ns commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

What was changed

Support Kotlin 2.4 async method references.

Why?

Kotlin 2.4 changed how it generated async method references breaking some optimization in the SDK and causing NDE

Checklist

  1. Closes Async.function/Async.procedure with a Kotlin method reference spawns a WorkflowThread per call instead of inlining, as it does the Java equivalent聽#2981

  2. How was this tested:

  1. Any docs updates needed?

Note

Medium Risk
Changes workflow async invocation and replay determinism for Kotlin method references; incorrect unwrapping could affect command ordering, though behavior is gated and documented via a system property.

Overview
Kotlin 2.4 compiles Async.function / Async.procedure method references as serialized lambdas with static adapters that lack Kotlin metadata, so the SDK no longer treated them as inline stub calls and replay could hit NonDeterministicException after upgrading from Kotlin 2.2.

The PR extends KotlinDetector and KotlinMethodReferenceDisassemblyService (Strategy 3) to recognize those adapters, unwrap the real stub target, and route them through the existing Kotlin async path in MethodReferenceDisassembler. A JVM flag temporal.kotlin.disableStaticAdapterUnwrapping preserves pre-fix replay behavior for workflows already started on Kotlin 2.4 with older SDKs. Edge CI is updated to compile temporal-kotlin with Kotlin 2.4.20, and KotlinAsyncMarkerTest covers marked-stub method references vs capturing lambdas.

Reviewed by Cursor Bugbot for commit a0d0314. Bugbot is set up for automated code reviews on this repo. Configure here.

@Quinn-With-Two-Ns
Quinn-With-Two-Ns requested a review from a team as a code owner October 1, 2026 17:23

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 1d2b815. Configure here.

@maciejdudko maciejdudko left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks good, but we should do better job documenting what we're fixing and why.

Comment thread temporal-kotlin/README.md Outdated
Comment on lines +24 to +28
To disable unwrapping Kotlin static adapters for method references passed to `Async`, set the
`temporal.kotlin.disableStaticAdapterUnwrapping` JVM system property. Its value does not matter;
for example, `-Dtemporal.kotlin.disableStaticAdapterUnwrapping` disables this fallback. This can
cause `Async` to stop recognizing method references compiled as static adapters.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expand on why the option exists (incompatibility between Kotlin 2.2 and 2.4 causing NDE when using older SDK <=1.40).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update both these let me know what you think

Comment thread CHANGELOG.md Outdated
Comment on lines +22 to +24
### Added
- Kotlin `Async` static adapter unwrapping can be disabled with the
`temporal.kotlin.disableStaticAdapterUnwrapping` JVM system property.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace with a note in Fixed section saying it fixes NDE when upgrading from Kotlin 2.2 to 2.4, and that already started 2.4 workflows can use temporal.kotlin.disableStaticAdapterUnwrapping.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Async.function/Async.procedure with a Kotlin method reference spawns a WorkflowThread per call instead of inlining, as it does the Java equivalent

2 participants