fix(compose): Restore Compose 1.6 compatibility for sentry-compose - #5887
Draft
runningcode wants to merge 3 commits into
Draft
fix(compose): Restore Compose 1.6 compatibility for sentry-compose#5887runningcode wants to merge 3 commits into
runningcode wants to merge 3 commits into
Conversation
…AVA-681) sentry-compose is compiled against androidx.compose.material3, which drags its own transitive compose-runtime and foundation versions onto the compile classpath. Since material3 was bumped to 1.4.0 in #5017, that raised those to runtime 1.9.0 and foundation-layout 1.8.1, well above the androidxCompose = 1.6.3 floor the module claims to support. Compose inlines composables such as Box into calling bytecode, so the published SentryComposeTracingKt contained no BoxKt.Box call at all and instead referenced Composer.shouldExecute (runtime 1.8.0+), BoxKt.maybeCachedBoxMeasurePolicy (foundation-layout 1.7.0+) and ComposableLambdaKt.rememberComposableLambda. On an app resolving an older Compose those symbols do not exist, so composing SentryTraced threw NoSuchMethodError. SentryUserFeedbackButton was affected the same way. Pin the compileOnly material3 used by sentry-compose to the oldest version we support instead, so the inlined internals stay resolvable on the declared floor. The unpinned alias is left untouched for the samples and test modules that need newer material3 APIs. Fixes SDK-CRASHES-JAVA-48AR Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…JAVA-681) Nothing asserted which Compose version sentry-compose stays loadable on, so the NoSuchMethodError fixed in the previous commit shipped unnoticed for 19 releases while the existing Compose tests kept passing. Those tests run on a recent Compose, where the inlined internals always resolve, so they cannot catch a floor mismatch by construction. Add a module that consumes sentry-compose with Compose forced to the declared floor and composes its public entry points. It needs to be separate because sentry-compose's own androidUnitTest pins ui-test-junit4 to 1.9.5, which would pull a newer Compose onto the test runtime and make the check pass regardless. The test runs under Robolectric, so it needs no emulator. Verified it fails with the exact production error when the material3 pin is reverted: java.lang.NoSuchMethodError: 'boolean androidx.compose.runtime.Composer.shouldExecute(boolean, int)' The module lives under sentry-android-integration-tests so the root build excludes it from publishing; a name containing "-compose" outside that path is treated as a publishable multiplatform artifact. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
📲 Install BuildsAndroid
|
Contributor
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| d15471f | 369.38 ms | 459.08 ms | 89.70 ms |
| bbc35bb | 324.88 ms | 425.73 ms | 100.85 ms |
| b193867 | 319.59 ms | 403.09 ms | 83.50 ms |
| 62b579c | 299.75 ms | 364.84 ms | 65.09 ms |
| 382d6c1 | 306.85 ms | 368.70 ms | 61.85 ms |
| 48277cd | 320.38 ms | 379.90 ms | 59.52 ms |
| 5b1a06b | 315.40 ms | 353.33 ms | 37.94 ms |
| ee747ae | 415.92 ms | 470.15 ms | 54.23 ms |
| 37ec571 | 366.04 ms | 424.28 ms | 58.23 ms |
| 462dea2 | 277.68 ms | 359.83 ms | 82.15 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| d15471f | 1.58 MiB | 2.13 MiB | 559.54 KiB |
| bbc35bb | 1.58 MiB | 2.12 MiB | 553.01 KiB |
| b193867 | 1.58 MiB | 2.19 MiB | 620.00 KiB |
| 62b579c | 0 B | 0 B | 0 B |
| 382d6c1 | 1.58 MiB | 2.29 MiB | 719.85 KiB |
| 48277cd | 0 B | 0 B | 0 B |
| 5b1a06b | 0 B | 0 B | 0 B |
| ee747ae | 1.58 MiB | 2.10 MiB | 530.95 KiB |
| 37ec571 | 0 B | 0 B | 0 B |
| 462dea2 | 0 B | 0 B | 0 B |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📜 Description
sentry-composewas shipping bytecode that references Jetpack Compose internals newer than the Compose floor the module declares (androidxCompose = "1.6.3"), so composingSentryTracedon an app with an older Compose threwNoSuchMethodError.androidx.compose.foundation.layout.Boxis an inline composable, so the Compose compiler bakes its body into our bytecode rather than leaving a call toBoxKt.Box. That means whatever Compose version is onsentry-compose's compile classpath gets inlined into the published artifact. The 8.51.0SentryComposeTracingKtcontains zeroBoxKt.Boxcall sites and instead references:BoxKt.maybeCachedBoxMeasurePolicyComposer.shouldExecuteComposableLambdaKt.rememberComposableLambdasentry-composedeclarescompileOnly(libs.androidx.compose.material3), and material3 drags its own transitive Compose onto that classpath. When material3 was bumped1.2.1 → 1.4.0in #5017 (a samples refactor), it pulled in runtime 1.9.0 / foundation-layout 1.8.1 and silently raised the floor of the inlined code.Bisecting published artifacts on Maven Central confirms where it regressed:
rememberBoxMeasurePolicy(resolvable on 1.6.x)maybeCachedBoxMeasurePolicy+shouldExecuteSentryUserFeedbackButtonwas affected the same way.The fix pins the
compileOnlymaterial3 used bysentry-composeto the oldest version we support via a newandroidx-compose-material3-floorcatalog alias. The unpinnedandroidx-compose-material3(1.4.0) is left untouched for the samples and test modules that need newer material3 APIs. No source or public API changes —apiDumpproduces no diff.The second commit adds
:sentry-android-integration-tests:compose-floor-integration-tests, which consumessentry-composewith Compose forced to the floor and composes both affected entry points. It has to be a separate module becausesentry-compose's ownandroidUnitTestpinsui-test-junit4to 1.9.5 — a test added there would run against new Compose and pass even with the bug present.Note
Seer's suggested autofix on SDK-CRASHES-JAVA-48AR (remove
propagateMinConstraints = truefrom theBox) is not the fix.BoxKt's public signature is identical from foundation-layout 1.5.4 through 1.11.2 —propagateMinConstraintshas always been a parameter. Removing it would change layout behavior and regress #2637 without addressing the crash.💡 Motivation and Context
Fixes SDK-CRASHES-JAVA-48AR (157 events, first seen 2026-03-19, reported on 8.51.0).
Linear: JAVA-681
Users on Compose older than 1.8 crash with an unhandled
NoSuchMethodErroras soon as aSentryTracedcomposable enters composition — the SDK takes down the host app.💚 How did you test it?
New Robolectric test module (no emulator needed), verified in both directions:
With the fix:
With the material3 pin reverted — reproduces the exact production error:
Also confirmed:
shouldExecute/maybeCachedBoxMeasurePolicy; onlyrememberBoxMeasurePolicy, which exists in foundation-layout 1.5.4 → 1.11.2 (backward and forward compatible).:sentry-compose:checkgreen — all 20 pre-existing tests pass.:sentry-samples-android:compileReleaseKotlingreen — samples still get material3 1.4.0, so the other five modules on the unpinned alias are unaffected.distZiptasks, so it won't ship to Maven Central.spotlessApply apiDumpclean, no API diff.📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps
Two things deliberately left out of this PR:
AbstractMethodErroron compose-ui 1.11+ fixed in fix(compose): add isImportantForBounds() to SentryTagModifierNode for compose-ui 1.11+ #5672 — needs a check against the newest Compose. Worth a follow-up.SentryUserFeedbackButtonconstraint. It genuinely uses material3 APIs (Button,Icon,Text), so pinning its compile version to 1.2.1 is what restores compatibility, but it also means that composable can't adopt newer material3 APIs without reintroducing this problem. It's already@Deprecatedfor removal in the next major, so this is likely fine — flagging it as a real constraint rather than a free win.Open question for reviewers: this restores the 1.6.3 floor. The alternative is to raise the documented minimum to Compose 1.8.0, which is simpler but a breaking change for users on older Compose and would need an explicit minimum-version statement in the docs. Happy to switch direction if that's preferred.