Skip to content

fix(compose): Restore Compose 1.6 compatibility for sentry-compose - #5887

Draft
runningcode wants to merge 3 commits into
mainfrom
no/java-681-compose-floor
Draft

fix(compose): Restore Compose 1.6 compatibility for sentry-compose#5887
runningcode wants to merge 3 commits into
mainfrom
no/java-681-compose-floor

Conversation

@runningcode

Copy link
Copy Markdown
Contributor

📜 Description

sentry-compose was shipping bytecode that references Jetpack Compose internals newer than the Compose floor the module declares (androidxCompose = "1.6.3"), so composing SentryTraced on an app with an older Compose threw NoSuchMethodError.

androidx.compose.foundation.layout.Box is an inline composable, so the Compose compiler bakes its body into our bytecode rather than leaving a call to BoxKt.Box. That means whatever Compose version is on sentry-compose's compile classpath gets inlined into the published artifact. The 8.51.0 SentryComposeTracingKt contains zero BoxKt.Box call sites and instead references:

Symbol First available in
BoxKt.maybeCachedBoxMeasurePolicy foundation-layout 1.7.0
Composer.shouldExecute runtime 1.8.0
ComposableLambdaKt.rememberComposableLambda runtime 1.8.0

sentry-compose declares compileOnly(libs.androidx.compose.material3), and material3 drags its own transitive Compose onto that classpath. When material3 was bumped 1.2.1 → 1.4.0 in #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:

  • 8.31.0 and earlier → rememberBoxMeasurePolicy (resolvable on 1.6.x)
  • 8.32.0 onward → maybeCachedBoxMeasurePolicy + shouldExecute

SentryUserFeedbackButton was affected the same way.

The fix pins the compileOnly material3 used by sentry-compose to the oldest version we support via a new androidx-compose-material3-floor catalog alias. The unpinned androidx-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 — apiDump produces no diff.

The second commit adds :sentry-android-integration-tests:compose-floor-integration-tests, which consumes sentry-compose with Compose forced to the floor and composes both affected entry points. It has to be a separate module because sentry-compose's own androidUnitTest pins ui-test-junit4 to 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 = true from the Box) is not the fix. BoxKt's public signature is identical from foundation-layout 1.5.4 through 1.11.2 — propagateMinConstraints has 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 NoSuchMethodError as soon as a SentryTraced composable 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:

ComposeFloorCompatibilityTest > SentryTraced composes on the oldest supported Compose PASSED
ComposeFloorCompatibilityTest > SentryUserFeedbackButton composes on the oldest supported Compose PASSED

With the material3 pin reverted — reproduces the exact production error:

ComposeFloorCompatibilityTest > SentryTraced ... FAILED
    java.lang.NoSuchMethodError: 'boolean androidx.compose.runtime.Composer.shouldExecute(boolean, int)'
ComposeFloorCompatibilityTest > SentryUserFeedbackButton ... FAILED  (same)

Also confirmed:

  • The test runtime genuinely resolves the floor (Compose 1.6.3, material3 1.2.1) — a check that silently ran on new Compose would be worthless here.
  • Emitted bytecode no longer references shouldExecute / maybeCachedBoxMeasurePolicy; only rememberBoxMeasurePolicy, which exists in foundation-layout 1.5.4 → 1.11.2 (backward and forward compatible).
  • :sentry-compose:check green — all 20 pre-existing tests pass.
  • :sentry-samples-android:compileReleaseKotlin green — samples still get material3 1.4.0, so the other five modules on the unpinned alias are unaffected.
  • The new module produces no publish/distZip tasks, so it won't ship to Maven Central.
  • spotlessApply apiDump clean, no API diff.

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

Two things deliberately left out of this PR:

  1. Ceiling coverage. This guards the floor only. The mirror-image failure — forward-incompatibility like the AbstractMethodError on 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.
  2. SentryUserFeedbackButton constraint. 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 @Deprecated for 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.

runningcode and others added 2 commits August 4, 2026 16:29
…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>
@linear-code

linear-code Bot commented Aug 4, 2026

Copy link
Copy Markdown

JAVA-681

@sentry

sentry Bot commented Aug 4, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.51.0 (1) release

⚙️ sentry-android Build Distribution Settings

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 401.36 ms 470.04 ms 68.68 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

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

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.

1 participant