GET /members Additionally Accepts Sync Tokens
Spec Requirement
Client-Server § GET /_matrix/client/v3/rooms/{roomId}/members
defines the optional at query parameter as a pagination token for the point in time whose
membership state should be returned. The spec says this token comes from a room’s
prev_batch field in a /sync response.
Arminius represents pagination tokens as MessagesToken values (m_<event_id>), as
described in the message pagination tokens ADR.
That format matches the spec’s intent, which is to be an opaque token tied to a
position in the room timeline.
Deviation
Arminius also accepts SyncToken values (s_<event_stream_position>_…, the next_batch
format from /sync) when resolving at.
If the parameter is a sync token, arminius maps its event stream position to the
latest room event at that position and uses that event as the snapshot point.
Strictly speaking, this is not what the spec describes. Unlike GET /messages,
which explicitly allows both prev_batch and next_batch, /members does not mention
next_batch at all.
Why
Element Web and Element Android pass sync tokens (next_batch) as at, not room
prev_batch tokens. Without accepting them, /members requests from Element fail
and encrypted rooms break when the client needs historical membership for
encryption setup.
This behavior is tracked in arminius#1765 and “discussed” upstream in matrix-spec#1302, where it remains unclear whether the spec text or the Element clients are wrong.
We accept sync tokens in addition to the spec-mandated behavior as a pragmatic compatibility measure until the spec clarifies the parameter or Element changes its behavior.
Implementation
Implemented in resolve_at_token in arminius-server-rooms (get_member_events.rs)
(Related Pull Request).