From bc20e64c615aedc611a3e50ede53501e77318238 Mon Sep 17 00:00:00 2001 From: hayaksi1 <193020925+hayaksi1@users.noreply.github.com> Date: Sun, 9 Aug 2026 04:08:55 +0300 Subject: [PATCH 1/2] Do not notify about a redaction whose target event is unknown A redaction push whose redacts field the SDK could not map was reported as an unknown error. The result processor only suppresses filtered-out and redacted events; every other exception becomes a visible "you have N notifications" fallback and also raises the battery optimisation banner. So a deleted message could produce a notification about itself, which is the opposite of what a redaction means, plus an unrelated banner. The branch now throws EventFilteredOut, which the processor already drops silently, and logs at warning level so the SDK gap still shows up in push history. Relates to https://github.com/element-hq/element-x-android/issues/5766 --- .../impl/notifications/DefaultNotifiableEventResolver.kt | 8 ++++++-- .../notifications/DefaultNotifiableEventResolverTest.kt | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt index abbda10a3c..beea34de76 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt @@ -284,8 +284,12 @@ class DefaultNotifiableEventResolver( // Note: this case will be handled below val redactedEventId = content.redactedEventId if (redactedEventId == null) { - Timber.tag(loggerTag.value).d("redactedEventId is null.") - throw NotificationResolverException.UnknownError("redactedEventId is null") + // Treat it as filtered out rather than as an error: an unknown error is turned + // into a visible "you have N notifications" fallback plus a battery banner, so a + // redaction we cannot map would notify about a message that was just deleted. + // See https://github.com/element-hq/element-x-android/issues/5766 + Timber.tag(loggerTag.value).w("Ignoring redaction notification with no redactedEventId.") + throw NotificationResolverException.EventFilteredOut } else { ResolvedPushEvent.Redaction( sessionId = userId, diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt index eedc107c67..2544b94543 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt @@ -818,7 +818,7 @@ class DefaultNotifiableEventResolverTest : RobolectricTest() { } @Test - fun `resolve RoomRedaction with null redactedEventId should return null`() = runTest { + fun `resolve RoomRedaction with null redactedEventId is filtered out`() = runTest { val sut = createDefaultNotifiableEventResolver( notificationResult = Result.success( mapOf( @@ -834,6 +834,9 @@ class DefaultNotifiableEventResolverTest : RobolectricTest() { val request = aPushRequest(A_SESSION_ID, A_ROOM_ID, AN_EVENT_ID, "firebase") val result = sut.resolveEvents(A_SESSION_ID, listOf(request)) assertThat(result.getEvent(request)?.getOrNull()).isNull() + // Must be EventFilteredOut and not an error: the result processor renders a fallback + // notification for any other exception, which is the bug in #5766. + assertThat(result.getEvent(request)?.exceptionOrNull()).isEqualTo(NotificationResolverException.EventFilteredOut) } @Test From fec71aaf4de6631fd85309a4186e3230ce8a51ac Mon Sep 17 00:00:00 2001 From: hayaksi1 <193020925+hayaksi1@users.noreply.github.com> Date: Sun, 9 Aug 2026 15:31:19 +0300 Subject: [PATCH 2/2] Drop the comments from the redaction resolution Review feedback: the filtered-out result and the test name already state why an unmappable redaction must not notify. --- .../push/impl/notifications/DefaultNotifiableEventResolver.kt | 4 ---- .../impl/notifications/DefaultNotifiableEventResolverTest.kt | 2 -- 2 files changed, 6 deletions(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt index beea34de76..e0b3209e33 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt @@ -284,10 +284,6 @@ class DefaultNotifiableEventResolver( // Note: this case will be handled below val redactedEventId = content.redactedEventId if (redactedEventId == null) { - // Treat it as filtered out rather than as an error: an unknown error is turned - // into a visible "you have N notifications" fallback plus a battery banner, so a - // redaction we cannot map would notify about a message that was just deleted. - // See https://github.com/element-hq/element-x-android/issues/5766 Timber.tag(loggerTag.value).w("Ignoring redaction notification with no redactedEventId.") throw NotificationResolverException.EventFilteredOut } else { diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt index 2544b94543..08315ff634 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt @@ -834,8 +834,6 @@ class DefaultNotifiableEventResolverTest : RobolectricTest() { val request = aPushRequest(A_SESSION_ID, A_ROOM_ID, AN_EVENT_ID, "firebase") val result = sut.resolveEvents(A_SESSION_ID, listOf(request)) assertThat(result.getEvent(request)?.getOrNull()).isNull() - // Must be EventFilteredOut and not an error: the result processor renders a fallback - // notification for any other exception, which is the bug in #5766. assertThat(result.getEvent(request)?.exceptionOrNull()).isEqualTo(NotificationResolverException.EventFilteredOut) }