From 661bb1e668c604a0ed8ebd54b87e833ba11968f1 Mon Sep 17 00:00:00 2001 From: Nelson Osacky Date: Tue, 1 Sep 2026 08:58:54 +0200 Subject: [PATCH 1/2] fix(core): Clear the persisted replay id when resetting the scope cache resetCache() clears every other persisted scope value on init but leaves replay.json in place, so a replay id written by a previous process can still be attached to events from the current one. The reset already runs after the integrations that consume those values, so deleting it here is safe. Co-Authored-By: Claude Opus 5 (1M context) --- .../sentry/cache/PersistingScopeObserver.java | 3 +++ .../PersistingScopeObserverBatchingTest.kt | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java index d6137ae051..03b9f17c65 100644 --- a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java +++ b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java @@ -378,5 +378,8 @@ public void resetCache() { delete(TAGS_FILENAME); delete(TRACE_FILENAME); delete(TRANSACTION_FILENAME); + // the replay this id points at belongs to the previous process, so it must not be attached to + // events from this one; the replay integration writes a fresh id once it starts recording + delete(REPLAY_FILENAME); } } diff --git a/sentry/src/test/java/io/sentry/cache/PersistingScopeObserverBatchingTest.kt b/sentry/src/test/java/io/sentry/cache/PersistingScopeObserverBatchingTest.kt index eec38e151e..d893e52d4c 100644 --- a/sentry/src/test/java/io/sentry/cache/PersistingScopeObserverBatchingTest.kt +++ b/sentry/src/test/java/io/sentry/cache/PersistingScopeObserverBatchingTest.kt @@ -6,7 +6,9 @@ import io.sentry.ISentryExecutorService import io.sentry.ISerializer import io.sentry.SentryOptions import io.sentry.cache.PersistingScopeObserver.BREADCRUMBS_FILENAME +import io.sentry.cache.PersistingScopeObserver.REPLAY_FILENAME import io.sentry.cache.PersistingScopeObserver.TRANSACTION_FILENAME +import io.sentry.protocol.SentryId import io.sentry.test.DeferredExecutorService import java.io.Writer import java.util.concurrent.atomic.AtomicBoolean @@ -28,6 +30,9 @@ class PersistingScopeObserverBatchingTest { private fun PersistingScopeObserver.readTransaction(): String? = read(options, TRANSACTION_FILENAME, String::class.java) + private fun PersistingScopeObserver.readReplayId(): String? = + read(options, REPLAY_FILENAME, String::class.java) + @Suppress("UNCHECKED_CAST") private fun PersistingScopeObserver.readBreadcrumbs(): List = read(options, BREADCRUMBS_FILENAME, List::class.java) as List @@ -118,6 +123,20 @@ class PersistingScopeObserverBatchingTest { } } + @Test + fun `resetCache clears the replay id left behind by the previous process`() { + val executor = DeferredExecutorService() + val sut = getSut(executor) + + sut.setReplayId(SentryId("afcb46b1140ade5187c4bbb5daa804df")) + executor.runAll() + assertThat(sut.readReplayId()).isEqualTo("afcb46b1140ade5187c4bbb5daa804df") + + sut.resetCache() + + assertThat(sut.readReplayId()).isNull() + } + @Test fun `resetCache keeps pending mutations from the current process`() { val executor = DeferredExecutorService() From 5cb116653ca6e483e843c29611d3559cc696084b Mon Sep 17 00:00:00 2001 From: Nelson Osacky Date: Tue, 1 Sep 2026 08:59:31 +0200 Subject: [PATCH 2/2] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 823c43f992..68656ebded 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Fixes - Keep dropped tombstone and ANR events dropped, instead of reporting the same app exit again at every app start ([#6002](https://github.com/getsentry/sentry-java/pull/6002)) +- Clear the persisted replay id on SDK init, so a replay id from a previous process is no longer attached to ANR events from the current one ([#6033](https://github.com/getsentry/sentry-java/pull/6033)) - Apply `Sentry.withScope` and `Sentry.withIsolationScope` data to events captured inside the callback when `globalHubMode` is enabled ([#6004](https://github.com/getsentry/sentry-java/pull/6004)) - `globalHubMode` is enabled by default on Android, where tags, extras, contexts and level set inside the callback were silently dropped - Scopes that are explicitly made current, e.g. via `Sentry.setCurrentScopes` or the `SentryContext` coroutine integration, are now also honoured when `globalHubMode` is enabled