@@ -850,6 +850,9 @@ handleRecvGossip = \events fromServer -> do
850850-- A → B forward based on stale gossip about R could land on B with no
851851-- actively-polling client and get stuck. If B refuses, A retries via
852852-- `retryPendingForwards` against the next presence target.
853+-- Re-delivery of an already-stored (toKey, blob) pair is treated as success
854+-- without a second append, so a sender whose success response was lost can
855+-- retry without duplicating the message in the recipient's mailbox.
853856handleForwardMessage : PubkeyHex -> BlobHex -> IO {rw *messages, r *presence, rw *seqCounter, clock} (Result HttpError {})
854857handleForwardMessage = \toKey encryptedBlob -> do
855858 t <- now
@@ -858,7 +861,8 @@ handleForwardMessage = \toKey encryptedBlob -> do
858861 if not hasLocalPresence pres toKey t
859862 then yield (Err {error: {status: 404, message: "no_presence"}})
860863 else do
861− appendMessage toKey encryptedBlob t
864+ msgs <- *messages
865+ when (not any (\m -> m.toKey == toKey && m.encryptedBlob == encryptedBlob) msgs) (appendMessage toKey encryptedBlob t)
862866 yield (Ok {value: {}}))
863867
864868-- ============================================