diff --git a/CHANGELOG.md b/CHANGELOG.md index 90ddcf1f068..a5d48eeb558 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ - Keep UI profiling running when `startProfiler` is called before a requested stop takes effect at the end of the current chunk ([#6291](https://github.com/getsentry/sentry-java/pull/6291)) - Before, the start call was ignored and the profiler still stopped at the end of the chunk, even in `TRACE` mode while sampled spans were active. On API 34 and lower, every later profile also stopped after one chunk. - Refuse to send data to servers whose certificate was issued by one of the leaked eMudhra intermediates (CVE-2026-111943) ([#6336](https://github.com/getsentry/sentry-java/pull/6336)) +- Stop sending the whole release as `dist` on ANR and app-exit events when the release has no `+versionCode` ([#6450](https://github.com/getsentry/sentry-java/pull/6450)) + - Relay rejected these values (e.g. `invalid character '@'`). `dist` is now left empty unless `options.dist` is set or the release contains a version code. ### Dependencies diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationExitInfoEventProcessor.java b/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationExitInfoEventProcessor.java index a82beb74121..80da05967ea 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationExitInfoEventProcessor.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ApplicationExitInfoEventProcessor.java @@ -532,16 +532,13 @@ private void setDist( event.setDist(getLaunchOption(DIST_FILENAME, String.class, options.getDist(), optionsSource)); } // if there's no user-set dist, fall back to versionCode from the release string + // (package@versionName+versionCode). Releases without a versionCode leave dist empty. if (event.getDist() == null) { final String release = event.getRelease(); if (release != null) { - try { - final String versionCode = release.substring(release.indexOf('+') + 1); - event.setDist(versionCode); - } catch (Throwable e) { - options - .getLogger() - .log(SentryLevel.WARNING, "Failed to parse release from scope cache: %s", release); + final int versionCodeSeparator = release.indexOf('+'); + if (versionCodeSeparator != -1) { + event.setDist(release.substring(versionCodeSeparator + 1)); } } } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitInfoEventProcessorTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitInfoEventProcessorTest.kt index aa08875a34e..12c1bf08429 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitInfoEventProcessorTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitInfoEventProcessorTest.kt @@ -746,6 +746,32 @@ class ApplicationExitInfoEventProcessorTest { assertEquals("232", processed!!.dist) } + @Test + fun `if dist is not persisted and release has no version code, leaves dist empty`() { + val hint = HintUtils.createWithTypeCheckHint(BackfillableHint()) + + val processor = fixture.getSut(tmpDir) + fixture.persistOptions(RELEASE_FILENAME, "io.sentry.samples@1.2") + + val processed = processor.process(SentryEvent(), hint) + + assertEquals("io.sentry.samples@1.2", processed!!.release) + assertNull(processed.dist) + } + + @Test + fun `if dist is not persisted and options release has no version code, leaves dist empty`() { + val hint = HintUtils.createWithTypeCheckHint(AbnormalExitHint(timestamp = 2_000)) + val processor = fixture.getSut(tmpDir) + fixture.options.release = "io.sentry.samples@1.2" + setLastUpdateTime(1_000) + + val processed = processor.process(SentryEvent(), hint)!! + + assertEquals("io.sentry.samples@1.2", processed.release) + assertNull(processed.dist) + } + @Test fun `merges user`() { val hint = HintUtils.createWithTypeCheckHint(BackfillableHint())