-
-
Notifications
You must be signed in to change notification settings - Fork 37
generateSentryProguardUuid deadlock with Kotlin 2.3 / Gradle 9.4.1 #1129
Description
Gradle Version
9.4.1
AGP Version
8.13.2
Code Minifier/Optimizer
R8
Version
6.3.0
Sentry SDK Version
8.34.1
Steps to Reproduce
The build fails because of a Gradle 9 task execution engine bug involving composite finalizer groups.
Sentry Gradle Plugin creates a task dependency structure that triggers this bug.
The generateSentryProguardUuid<variant> task has zero dependencies but cannot start because Gradle placed it in a composite finalizer group — it simultaneously belongs to two finalizer chains:
- APK listing chain:
createDebugApkListingFileRedirect→packageDebug→compressDebugAssets→injectSentryDebugMetaProperties→generateSentryProguardUuidDebug - Sentry upload chain:
uploadSentryProguardMappingsDebug→generateSentryProguardUuidDebug+mergeDebugComposeMapping
Gradle 9's execution planner sees generateSentryProguardUuidDebug in both finalizer groups and enters a state where it can't determine which group to activate first. All workers stop. The build deadlocks.
Results in a build error that looks something like this (when assembling with R8):
Unable to make progress running work. The following items are queued for execution but none of them can be started:
- Build ':':
- Waiting for nodes:
- :demo-app:uploadSentryProguardMappingsDebug (state=SHOULD_RUN, dependencies=NOT_COMPLETE, group=finalizer :demo-app:uploadSentryProguardMappingsDebug ordinal: task group 0, delegate: default group, dependencies=[:demo-app:generateSentryProguardUuidDebug (SHOULD_RUN), :demo-app:mergeDebugComposeMapping (SHOULD_RUN)], waiting-for=[:demo-app:mergeDebugComposeMapping (SHOULD_RUN), :demo-app:generateSentryProguardUuidDebug (SHOULD_RUN)], has-failed-dependency=false, finalizes=[:demo-app:assembleDebug (SHOULD_RUN)] )
- :demo-app:assembleDebug (state=SHOULD_RUN, dependencies=NOT_COMPLETE, group=task group 0, dependencies=[:demo-app:mergeDebugNativeDebugMetadata (EXECUTED), :demo-app:packageDebug (SHOULD_RUN)], waiting-for=[:demo-app:packageDebug (SHOULD_RUN)], has-failed-dependency=false )
- :demo-app:createDebugApkListingFileRedirect (state=SHOULD_RUN, dependencies=NOT_COMPLETE, group=finalizer :demo-app:createDebugApkListingFileRedirect ordinal: task group 0, delegate: default group, dependencies=[:demo-app:packageDebug (SHOULD_RUN)], waiting-for=[:demo-app:packageDebug (SHOULD_RUN)], has-failed-dependency=false, finalizes=[:demo-app:packageDebug (SHOULD_RUN)] )
- Reachable nodes:
- :demo-app:mergeDebugComposeMapping (state=SHOULD_RUN, dependencies=NOT_COMPLETE, group=finalizer :demo-app:uploadSentryProguardMappingsDebug ordinal: task group 0, delegate: default group, dependencies=[:demo-app:minifyDebugWithR8 (EXECUTED), :demo-app:produceDebugComposeMapping (EXECUTED)], has-failed-dependency=false )
- :demo-app:generateSentryProguardUuidDebug (state=SHOULD_RUN, dependencies=NOT_COMPLETE, group=finalizer :demo-app:generateSentryProguardUuidDebug ordinal: task group 0, delegate: composite group, entry point: true, ordinal: task group 0, groups: [finalizer :demo-app:createDebugApkListingFileRedirect ordinal: task group 0, delegate: default group, finalizer :demo-app:uploadSentryProguardMappingsDebug ordinal: task group 0, delegate: default group], no dependencies, finalizes=[:demo-app:mergeDebugComposeMapping (SHOULD_RUN)] )
- :demo-app:injectSentryDebugMetaPropertiesIntoAssetsDebug (state=SHOULD_RUN, dependencies=NOT_COMPLETE, group=composite group, entry point: true, ordinal: task group 0, groups: [finalizer :demo-app:createDebugApkListingFileRedirect ordinal: task group 0, delegate: default group], dependencies=[:demo-app:generateSentryProguardUuidDebug (SHOULD_RUN), :demo-app:mergeDebugAssets (EXECUTED)], waiting-for=[:demo-app:generateSentryProguardUuidDebug (SHOULD_RUN)], has-failed-dependency=false )
- :demo-app:compressDebugAssets (state=SHOULD_RUN, dependencies=NOT_COMPLETE, group=composite group, entry point: true, ordinal: task group 0, groups: [finalizer :demo-app:createDebugApkListingFileRedirect ordinal: task group 0, delegate: default group], dependencies=[:demo-app:injectSentryDebugMetaPropertiesIntoAssetsDebug (SHOULD_RUN), :demo-app:preDebugBuild (EXECUTED)], waiting-for=[:demo-app:injectSentryDebugMetaPropertiesIntoAssetsDebug (SHOULD_RUN)], has-failed-dependency=false )
- :demo-app:packageDebug (state=SHOULD_RUN, dependencies=NOT_COMPLETE, group=composite group, entry point: true, ordinal: task group 0, groups: [finalizer :demo-app:createDebugApkListingFileRedirect ordinal: task group 0, delegate: default group], dependencies=[:demo-app:compileDebugJavaWithJavac (EXECUTED), :demo-app:compressDebugAssets (SHOULD_RUN), :demo-app:l8DexDesugarLibDebug (EXECUTED), :demo-app:mergeDebugAssets (EXECUTED), :demo-app:minifyDebugWithR8 (EXECUTED), :demo-app:preDebugBuild (EXECUTED), :demo-app:processDebugManifestForPackage (EXECUTED), :demo-app:processDebugResources (EXECUTED), :demo-app:stripDebugDebugSymbols (EXECUTED), :demo-app:validateSigningDebug (EXECUTED), :demo-app:writeDebugAppMetadata (EXECUTED), :demo-app:writeDebugSigningConfigVersions (EXECUTED)], waiting-for=[:demo-app:compressDebugAssets (SHOULD_RUN)], has-failed-dependency=false )
- Ordinal groups:
- group 0 entry nodes: [:demo-app:assembleDebug (SHOULD_RUN)]
- Workers waiting for work: 10
- Stopped workers: 8
Tried with Gradle 9.2.1 and also latest version 9.4.1; same error.
We also found a temporary work around:
// Workaround for Gradle 9.x task scheduler deadlock with Sentry plugin + Kotlin 2.3.
// Kotlin 2.3's compose compiler introduces mergeXxxComposeMapping tasks that transform
// the OBFUSCATION_MAPPING_FILE artifact. The Sentry plugin's toListenTo API (AGP 8.3+)
// registers generateSentryProguardUuid as a finalizer of the compose mapping merge task.
// This finalizer relationship, combined with the inject-assets dependency chain and
// AGP's own finalizer groups, creates an unresolvable composite group scheduling deadlock.
// Fix: replace the finalizer relationship with a regular dependsOn, preserving execution
// order without causing cross-group scheduling conflicts.
afterEvaluate {
android.applicationVariants.configureEach { variant ->
def variantName = variant.name.capitalize()
def mergeTask = tasks.findByName("merge${variantName}ComposeMapping")
def uuidTask = tasks.findByName("generateSentryProguardUuid${variantName}")
if (mergeTask != null && uuidTask != null) {
mergeTask.setFinalizedBy([])
uuidTask.dependsOn(mergeTask)
}
}
}Expected Result
Should not deadlock and fail build
Actual Result
Builds fail
Metadata
Metadata
Assignees
Labels
Fields
Give feedbackProjects
Status