From b0b4203cb6090b9c79e597d65eadebb5b3fbb843 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 17 Feb 2026 07:04:17 -0600 Subject: [PATCH] Fix `/sync` missing membership in `state_after` (#19463) --- changelog.d/19463.bugfix | 1 + synapse/handlers/sync.py | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 changelog.d/19463.bugfix diff --git a/changelog.d/19463.bugfix b/changelog.d/19463.bugfix new file mode 100644 index 0000000000..fe44c2ddf6 --- /dev/null +++ b/changelog.d/19463.bugfix @@ -0,0 +1 @@ +Fix `/sync` missing membership event in `state_after` (experimental [MSC4222](https://github.com/matrix-org/matrix-spec-proposals/pull/4222) implementation) in some scenarios. diff --git a/synapse/handlers/sync.py b/synapse/handlers/sync.py index 72e91d66ac..ab050adb26 100644 --- a/synapse/handlers/sync.py +++ b/synapse/handlers/sync.py @@ -1041,9 +1041,18 @@ class SyncHandler: if event.sender not in first_event_by_sender_map: first_event_by_sender_map[event.sender] = event - # We need the event's sender, unless their membership was in a - # previous timeline event. - if (EventTypes.Member, event.sender) not in timeline_state: + # When using `state_after`, there is no special treatment with + # regards to state also being in the `timeline`. Always fetch + # relevant membership regardless of whether the state event is in + # the `timeline`. + if sync_config.use_state_after: + members_to_fetch.add(event.sender) + # For `state`, the client is supposed to do a flawed re-construction + # of state over time by starting with the given `state` and layering + # on state from the `timeline` as you go (flawed because state + # resolution). In this case, we only need their membership in + # `state` when their membership isn't already in the `timeline`. + elif (EventTypes.Member, event.sender) not in timeline_state: members_to_fetch.add(event.sender) # FIXME: we also care about invite targets etc.