[XMPP · Offline Delivery] Messages rejected with resource-constraint are later received and read #3
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?
[XMPP · Offline Delivery] Messages rejected with resource-constraint are later received and read
Status: Investigation required. The contradiction between the reported rejection and subsequent delivery is confirmed by client logs, but the affected component and root cause are unknown.
Related confirmed UI issue: BUG_96_failed_status_persists_after_read_receipt.zip
Summary
Two messages sent to a suspended recipient received:
server_status=failed
fail_reason=resource-constraint
"Your contact offline message queue is full. The message has been discarded."
However, after the recipient reconnected, both messages were present in the chat, and the sender later received remote_status=read for the same message IDs.
Offline queue overflow itself is not reported as a bug here. The issue is the inconsistency between the reported rejection and the later confirmed delivery.
Environment
Sender: testman421@another.im, iPhone 13 Pro Max, iOS 26.7.1
Recipient: testman435@another.im, iPhone 17 Pro Max, iOS 27.2
App: v1.1.0 build 96 (feat/ui-redesign@e945d7cc)
libtacky: v1.2.0-rc4
1:1 OMEMO chat
Observed sequence
Recipient B was suspended and the device was locked.
Sender A sent two messages.
At 15:49:25 UTC, A received resource-constraint failures for both messages.
B reconnected at 15:51:29 UTC.
Both messages appeared on B after reconnect.
At 15:55:06 UTC, A received remote_status=read for both original message IDs.
A control message sent later was also delivered and read without a failure during the observed interval.
Message Sent (UTC) Failure (UTC) Read (UTC)
QA96_PUSH_LOCKED_02 15:44:25.264 15:49:25.488 15:55:06.044
QA96_PUSH_LOCKED_03 15:46:20.423 15:49:25.505 15:55:06.047
QA96_PUSH_ROUTE_04 (control) 15:53:02.088 — 15:55:06.049
For one of the affected messages, B's local record contains the same origin_id as the original send on A.
Investigation requested
Please correlate the message/stanza and origin IDs with server logs for 15:43–15:56 UTC on November 6, 2026, and determine:
the actual cause and scope of the resource-constraint errors;
the offline queue state and enqueue/dequeue activity at the time of the failures;
whether the messages were archived and how B later received them;
whether multiple copies or repeated processing were involved;
which delivery stage and stanza the error refers to;
how the backend should resolve the combination of server_status=failed and remote_status=read.
Limitations
Server logs and offline queue state were not available during testing. Queue limits were not changed or cleared.
The client evidence confirms the rejection events, subsequent presence of the messages on B, and read receipts for the same IDs. It does not establish whether the later delivery came through the offline queue, MAM, or another mechanism.
Completion criterion: establish the cause of the rejection and the path of subsequent delivery for the same message IDs, then determine whether a server or backend defect exists and define a separate reproducible scenario if necessary.
Analysis (anotherim-swift, 2026-11-07)
Not reproduced; read from
ejabberd/ejabberd.ymland libtacky. The timing is the strongest evidence.max_user_offline_messagesis 100 for everyone (ejabberd.yml :319-321, used bymod_offline:387-388).mod_mamhasassume_mam_usage: true,default: always(:373-376).mod_push_keepalivekeeps a push-hibernated session for 24 h, cut to 5 minutes by the first incoming message (:472-486).mod_stream_mgmthasresend_on_timeout: if_offline(:552-553).mod_offline, whose queue was full, and both bounced at the same instant with "Your contact offline message queue is full. The message has been discarded." Both were already archived, so B got them from MAM on reconnect, and the read receipts followed.To confirm: the server's debug log at 15:49:25 UTC on 2026-11-06 ("Re-routing 2 unacknowledged…" vs. "Dropping archived…"), and what filled B's offline queue (receipts/markers stored as empty bodies? the queue is flushed only by a fresh session's initial presence). From memory of upstream,
assume_mam_usageshould drop archived stanzas instead of re-routing them; why it did not here is open (needs the 26.09 source).Proposed: mitigate with a higher
max_user_offline_messages(e.g. 1000) andmod_offline: store_empty_body: false; properly, do not bounce a message that is already in the recipient's archive (astore_offline_messagehook, e.g. in mod_apush, dropping it without an error).Cause found:
mod_offlinekept a full copy of every message, including ones already archived by MAM, and counted both toward its queue limit. Once 100 were waiting, a push-held session that re-routed its messages at the end of its hold could overflow that limit and bounce messages withresource-constraint, even though the same messages were already in the recipient's archive and would be delivered from there once they reconnected. That is why the sender saw a failure but the recipient later received and read the message.Fix:
mod_offlinenow usesuse_mam_for_storage: true, so an already-archived message is only counted, not stored a second time, and no longer bounces for queue space. A Bind 2 sign-in empties the spool and catches up from MAM anyway, so nothing is lost either way. Released in anotherim-server v2026.11.07 (https://dev.another.im/another-im/anotherim-server/releases/tag/v2026.11.07), with a newmake test-offlineregression test.This needs a deployment step: production is still on the image/config from before this fix and needs the
use_mam_for_storage: trueline added tomod_offline's config andreload_configrun (or a restart). That deployment is still pending as of this comment.