Skip to content

DM path ignores had_unregistered_device, so a 406 never invalidates the device cache #1135

Description

@jlucaso1

A 406 from a recipient device means the server considers that device unregistered, so the cached device list we fanned out to is stale. The group path acts on that; the DM path does not.

Where it diverges

encrypt_for_devices_with_sessions_raw_detailed records the condition (wacore/src/send/encrypt.rs:708, had_unregistered_device: had_406) and both wrappers propagate it faithfully (:425, :782).

The group path reads it (wacore/src/send/group.rs:448 and :465): it feeds collect_stale_device_users, surfaces the stale users through RequiredSenderKeyDistributionError, and sets the had_unregistered_devices flag that drives the device-cache invalidation.

On the DM path nothing reads it. prepare_dm_stanza gets the summary and drops the flag, so a DM to a device the server has since dropped fans out to the stale entry, gets a 406 for it, and leaves the cache exactly as it was. The next DM to the same chat repeats the fan-out against the same stale device.

Why this is being filed and not fixed

Pre-existing behaviour, not a regression. It surfaced while reviewing #1131, which introduced encrypt_for_devices_into for the DM path; a reviewer noticed the field is now more visibly unused there. #1131 deliberately did not change it, since that PR is about allocation counts and this is a behaviour change on the send path.

What a fix would need to decide

  • Whether a DM 406 should invalidate the whole user's device list, or only the offending device. The group path collects stale users, which is coarser than a DM needs.
  • Whether to invalidate eagerly or on the next send. invalidate_device_cache already exists (src/send/mod.rs:1257); the question is whether the DM path should call it inline, which costs a usync on the next send, or mark the entry so the next fan-out refreshes.
  • What happens when the 406 device is the only one. The send already fails; invalidating first would make the retry meaningful instead of repeating the same fan-out.

Reproducing it

Not reproducible against the mock harness as-is: it would need a barback scenario that answers a device with a 406 while keeping the rest of the fan-out healthy, then asserts a second send re-runs usync for that user. Worth adding alongside the fix, since without it a regression here is invisible: the symptom is a wasted round trip, not an error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions