Skip to main content

Breaking changes

is_on_whatsapp rejects unsupported JID types (#817) Passing a non-PN/non-LID JID (group, newsletter, etc.) to contacts().is_on_whatsapp() now returns an error immediately. Previously the method silently dropped those JIDs with a warn! log, making it easy to miss the ignored input.
// This now returns Err("is_on_whatsapp only supports PN and LID JIDs, got …")
client.contacts().is_on_whatsapp(&[Jid::group("120363021033254949")]).await?;
Validate that your inputs to is_on_whatsapp contain only Jid::pn(...) or Jid::lid(...) values. IqError::UnexpectedResponseType added (#817) IQ responses whose type attribute is neither result nor error (e.g. get, set, or absent) now produce IqError::UnexpectedResponseType { got: Option<String> } instead of being silently accepted. If you exhaustively match on IqError, add an arm for this variant. It is classified as a transient keepalive failure.

New fields

Per-subprotocol error fields on IsOnWhatsAppResult and UserInfo (#817) The usync response parser now preserves server-returned per-subprotocol errors instead of silently omitting the associated field. Both result types gain new Option<UsyncSubprotocolError> fields: IsOnWhatsAppResult gains:
  • contact_error — server error for the contact lookup subprotocol
  • lid_error — server error for the LID resolution subprotocol
  • business_error — server error for the business-info subprotocol
UserInfo gains:
  • lid_error, status_error, picture_error, business_error, devices_error
UsyncSubprotocolError is a new public type:
pub struct UsyncSubprotocolError {
    pub code: Option<u16>,
    pub text: Option<String>,
    pub backoff: Option<u32>,
}
When a subprotocol error is present its corresponding data field (lid, status, picture_id, etc.) will be None / false / empty. Check *_error when you need to distinguish “not returned” from “server refused”. Both structs are #[non_exhaustive]; add .. to any exhaustive struct destructuring that matches them.

Fixes & hardening

Device-list and LID batch queries degrade per user (#817) DeviceListSpec and LidQuerySpec now skip individual users whose <devices> or <lid> subprotocol node contains an error, rather than letting that error propagate and fail the entire batch. A server-side per-user error (e.g. a temporarily unavailable device list for one noisy participant) no longer blocks sends to the rest of the group. A result-level devices subprotocol error is demoted to a warn! log rather than an abort, matching WA Web behavior. App-state MAC validation ignores hasMissingRemove bypass (#817) hasMissingRemove was previously used to skip snapshot and patch MAC validation when a REMOVE mutation was missing its prior value, matching a misread of WA Web’s behavior. WA Web actually tracks this flag only as telemetry for MAC-failure diagnostics and always rejects MAC mismatches. The bypass is removed; MAC mismatches are now fatal regardless of hasMissingRemove. Retry receipts: peer-device retry without recipient is aborted (#817) A retry receipt from a peer device (your own linked device) that omits the recipient attribute has no resolvable target chat — WA Web returns null in this case. Previously the library logged a warning and fell back to from.to_non_ad(), which would produce a failing message lookup anyway. The receipt is now silently dropped rather than proceeding with a wrong chat target. Retry key bundles require a one-time prekey for regular retries (#817) Regular retry receipts (non-FBID-bot) must include a <key> (one-time prekey) child in the <keys> bundle. Bundles missing the one-time prekey are now rejected with an explicit error. The exception is primary @bot FBID bot retries, which follow WA Web’s bot_retry parser path and may proceed with identity + signed prekey alone. Rejected key bundles abort retry resend (#817) When a <keys> node is present but the key bundle is rejected (e.g. ADV validation failure, missing prekey), the retry resend is now aborted immediately. Previously the code logged a warning and continued, potentially sending with a stale or wrong session. AD-JID decoder rejects unknown domain type bytes (#817) The binary-protocol AD-JID decoder now returns a parse error for domain type bytes that do not map to a known server (the WA Web decodeJidU behavior). Previously unknown bytes silently mapped to PN, masking malformed protocol frames. ADV NoAccountKey log downgraded to debug (#817) The log emitted when a companion device’s pre-key bundle or retry bundle omits account_signature_key and no stored account identity is available has been downgraded from warn to debug. This server shape is legitimately common when no account identity has been cached yet; the warn level created noise without being actionable.