Menu 0.6.0 preview

Integrate

Delivery issues

This page states the delivery-issue stream in the Developer Preview as trueseal-sync ADR-0026 decides it, with the cases of ADR-0028 as amended by ADR-0034. The delivery promise and state machines are on Sending and receiving.

Stream

  • onDeliveryIssue(listener) registers a listener and returns a cancel handle. It is optional. Ignoring it is safe.
  • Each issue carries a Message ID where one exists, and a reason.
  • Issues are device-local. Nothing is sent to the sender or the relay.

Cases

CaseWhat happenedWhat to do
unreadable(malformed) A message the library can't use was acknowledged and dropped. Its bytes couldn't be decoded or authenticated, or it carried an unknown frame type or message tag. Nothing. Log it if you collect diagnostics.
unreadable(senderOutdated) A message the library can't use was acknowledged and dropped. Another device sent it in an older End-to-End Version than this device supports. Tell the user one of their other devices needs an update.
unreadable(expired) A message the library can't use was acknowledged and dropped. Its Sender Timestamp is older than the Replay Window. Replay Window: 60 days. Nothing. The data is lost on this device. If it matters, ask another device to send its current state again.
unreadable(droppedWhileHeld) A message the library can't use was acknowledged and dropped. More newer-version messages than the Held-Blob cap were waiting for this device, and this was the oldest. Held-Blob cap: 100 Blobs per device. Ask the user to update the app now. Messages are already being lost.
unauthorized A message failed the pairing or membership rules, for example its sender isn't a member, and was acknowledged and dropped. Nothing. Log it if you collect diagnostics.
heldForUpgrade(version) A message in a newer End-to-End Version waits on the relay, unacknowledged, until this device upgrades. Ask the user to update the app. After the upgrade the message is handled, out of order with the messages around it.
handlerGaveUp(messageId, error) The message handler threw on every attempt, and the message was acknowledged and dropped. Handler attempts: 5 attempts. Treat it as a bug in the handler. Log messageId and report error. If the data matters, ask the sending device to send it again.
sendFailed(messageId, tooLarge) An outbox entry was removed for good, so the recipient never gets that message. Messages sent after it still arrive. The relay refused it because it is over the relay's Relay Size Limit, which an Operator may set below the Protocol Size Limit. Tell the user the message wasn't delivered. Send smaller messages, or pass a matching lower maxPayloadBytes to open() so send() refuses them up front. maxPayloadBytes counts the body, and the Relay Size Limit counts the sealed envelope.
sendFailed(messageId, malformed) An outbox entry was removed for good, so the recipient never gets that message. Messages sent after it still arrive. The relay refused it because it couldn't parse it. Treat it as a bug and report it.
sendFailed(messageId, expired) An outbox entry was removed for good, so the recipient never gets that message. Messages sent after it still arrive. It was a Sync entry still in the outbox after the Outbox expiry, for example because the device was offline all that time. Outbox expiry: 30 days. Tell the user it wasn't delivered, and send it again if it still matters.

The Relay Size Limit and maxPayloadBytes are on Relay limits and quotas.

undeliverableAfterUpgrade no longer exists (ADR-0034). An End-to-End Version upgrade re-seals every outbox entry and loses none.

Relay push refusals

  • Permanent: too large and malformed. The outbox entry is removed and sendFailed is raised with the matching reason, tooLarge or malformed.
  • Temporary: inbox full, rate limited, unavailable and internal error. The library retries with backoff and raises no issue.

The codes carry no content.

Errors thrown when sending

send() throws these before anything enters the outbox. They never appear on the stream.

CaseWhat happenedWhat to do
closed A call on a TrueSeal object after close(). Open a new object with TrueSeal.open. A closed object stays closed.
notMember{status} send() while the status is not member. Check status before calling, and hide the send action until it is member. Offer pairing while it is notJoined or pendingJoin.
payloadTooLarge{max} send() with a body over max, the Protocol Size Limit or the lower maxPayloadBytes passed to open(). Nothing enters the outbox. Protocol Size Limit: 61,440 bytes (60 KiB). Send a smaller body. Split the data, or store it elsewhere and send a reference.

Connection state

An unsupported Transport Version sets connection to relayVersionUnsupported{min, max}. No issue is raised and outbox entries stay queued until the library is upgraded.

Never reported

  • A Blob deleted by the relay after its TTL. The sender saw the push ack; the recipient never saw the Blob.
  • A duplicate, acked silently.
  • Pending Sync sends dropped on a deliberate removal or on entering destroying, on the initiating and the receiving devices (ADR-0027, ADR-0029).