Broaden MP cache-invalidate to all messageprotection-* codes#28
Broaden MP cache-invalidate to all messageprotection-* codes#28dav12072018 wants to merge 1 commit into
Conversation
Previously only "ec-com.apple.messageprotection-802" triggered identity cache invalidation on a command:120 error. The same recovery path (invalidating the cached per-device session keys for the failing pair) also resolves "-6" (signature/decrypt verification failed on the recipient device) and other recoverable message-protection codes that indicate a stale per-device session key. Without this, MP-6 errors propagate to the UI as send failures even when Apple's IDS already accepted and delivered the message to the chat recipient. This is particularly visible for self-loop errors (sP == tP) where the user's own other devices reject the reflected copy: the chat recipient sees the message, but the sender's OpenBubbles UI marks it failed and never recovers because the stale cached session keeps producing the same failure on retry. Refs: openbubbles-app#206
|
Hi, Your PR appears to be written by AI - can you please provide your source for the meaning of errors -6 and -802? Thank you. |
What I have for -802: the existing comment in your own code (// refreshing identity cache can fix this) plus the fact that you already special-case it. That's not a source for what -802 means, just confirmation that you've already treated it as a recoverable cache-invalidation case. What I have for -6: I don't have a documented Apple source. Apple's iMessage protection error codes aren't publicly documented anywhere I could find. My reasoning was inferential, from log evidence in one user's rustpush trace: 81 MP-6 errors in 9 hours, 100% self-loops (sP == tP), all with fR: 200 (Apple's relay accepted the send) See this for the full investigation. OpenBubbles/openbubbles-app#206 |
What this changes
One-line behavioral change in
src/imessage/aps_client.rs(command:120 error handling). Previously onlyec-com.apple.messageprotection-802invalidated the per-pair identity cache; this PR broadens that to anyec-com.apple.messageprotection-*code.Why
Filed as OpenBubbles/openbubbles-app#206 (full investigation and log evidence there). Short version:
messageprotection-6(signature/decrypt verification failed) and-802(NGM count drift) are both downstream symptoms of the same root condition — the per-device session key in rustpush's identity cache is stale relative to what the recipient device actually has. The recovery path (invalidate the cached pair, force a fresh IDS lookup on next send) works for both.Without this fix, MP-6 errors propagate to the Dart UI as
Message::Errorand are rendered as send failures, even when Apple's IDS already accepted and delivered the message to the chat recipient. This is especially visible for self-loop errors (sP == tP) — the user's own other devices rejecting the reflected copy — where every retry hits the same stale cached key and produces the same MP-6, so the user sees a permanent "failed to send" state on messages that actually delivered.Evidence from one user's log over 9 hours:
sP == tP)fR: 200on all of them — Apple acked delivery; the per-recipient decryption failedTested by
In particular, the assumption being made is that every
ec-com.apple.messageprotection-*code is recoverable via cache invalidation. If there are MP codes that should not invalidate the cache (e.g. ones indicating the recipient is permanently gone, or where invalidation would trigger a tight retry loop), this would need a more targeted match — for example an allowlist of known recoverable codes, or excluding specific ones.I marked this draft for that reason. Happy to narrow the match (e.g. just
-6+-802) ifstarts_withis too broad.Alternative considered
A more semantically correct fix would be in
process_msg: detect self-loop errors (sP == this client's own handle) and suppress them from being surfaced asMessage::Errorto the Dart layer at all, since the chat recipient already got the message. That would be a larger change and I wasn't sure of the right way to compare against the client's own registered handles in this code — happy to attempt that direction instead if preferred.Refs: OpenBubbles/openbubbles-app#206