[iOS · Disappearing Messages · #19] Disappearing message remains visible in an open chat after expiry and disappears only after reopening #27
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
[iOS · Disappearing Messages · #19] Disappearing message remains visible in an open chat after expiry and disappears only after reopening
Build: TestFlight 1.1.0 (96)
Date: November 6, 2026
Result: Reproduced. Acceptance item #19 remains open.
Related: #19
Summary
A disappearing message remains visible in an open conversation after its expiry timer has elapsed, even though the backend reports a message Expired event.
The message disappears after leaving and reopening the chat. This suggests that the active transcript is not updated when the expiry event is received.
Environment
Sender (A): iPhone 13 Pro Max, iOS 26.7.1, build 96, testman421@another.im
Recipient (B): iPhone 17 Pro Max, iOS 27.0.1, build 96, testman435@another.im
1:1 chat with OMEMO enabled
Steps to reproduce
With Disappearing Messages disabled, send a control message.
Enable Disappearing Messages → 5 minutes.
Send a message and edit it.
Open/read the message on the other device.
Keep the chat open on both devices for more than five minutes.
Check whether the message disappears without navigating away.
Leave the chat and open it again.
Expected result
Once the message expires, it should automatically disappear from the currently open transcript without requiring navigation, a new incoming message, or an application restart.
Messages sent before the disappearing-message timer was enabled should remain.
Actual result
The edited disappearing message remained visible in the open chat after expiry.
On device A:
message Expired was logged at 13:12:53 UTC.
At 13:20 UTC, more than seven minutes later, the expired message was still visible on screen.
According to the tester, the message disappeared after leaving and reopening the chat.
The control message remained, and searches for both the original and edited versions of the expired text returned no results.
Expiry events were present in diagnostics from both devices.
Diagnostics
Device UTC Event
A 13:06:37 ephemeral set_timer, seconds=300
A 13:07:53 Message sent
A 13:08:26 Message edited
A 13:12:53 message Expired
B 13:07:54 message mark_displayed
B 13:14:26 message Expired
The difference in expiry timestamps between the two devices was not investigated as part of this issue.
Suspected cause
Source review of build 96 (
529d77d) found that the Swift event mapping handles message Removed, but does not handle message Expired; unknown events are mapped to other.The existing Removed path removes the message from the active transcript:
XMPPEventKind.from maps message Removed to messageRemoved.
ConversationClient converts it to ConversationEvent.removed.
TranscriptWindow removes the message from the current rows.
Generated TackyWire documentation describes Expired as removing the message and its edits when preserve_history=0, and indicates that it should be handled as Removed by timestamp.
The missing Expired handling is consistent with the observed behavior, but the exact causal chain should be confirmed by development.
Retest criteria
Repeat the scenario with a new control message and a new disappearing message while keeping the chat open.
After Expired, the message must disappear on both devices without navigation or restart.
The message sent before enabling the timer must remain.
The expired message must not reappear after reopening the chat or restarting the app.
Search should return no results for either the original or edited version.
Repeat the same test with an unedited disappearing message.
Fixed in branch
fix/app-issues-25-28(https://dev.another.im/another-im/anotherim-swift/compare/master...fix/app-issues-25-28), commit0a6073fd: libtacky'smessage <Expired>(what the app gets, since it keeps no history:preserve_history0) was not mapped and became.other, so the open transcript kept the row until the chat was reopened. It is now handled asRemovedof its timestamp, as TackyWire says; edits go with the row in libtacky's store. Test: ConversationLiveEventsTests playsExpired. Left: the chat list's preview keeps the expired text until the list's next update, since libtacky's chatlist does not follow<Expired>: another-im/libtacky#23.