Sync: $ME and $LAZY in required_state are not resolved #1661

Closed
opened 2026-04-14 19:46:11 +00:00 by kiorul · 9 comments

As described in MSC3575 [EDIT: previous versions of MSC4186 that are still in use by other homeservers like Synapse and Tuwunel, see comment below], *, $ME and $LAZY in required_state are special sentinel values that Continuwuity must resolve. However, $ME and $LAZY are currently not handled in collect_required_state in src/api/client/sync/v5.rs. Only * is considered there.

Some clients, especially those relying on the official Matrix Rust SDK, expect these values to be resolved. For example, Element X (iOS and Android), which uses it, fails to load the push rules because $ME is not handled correctly by Continuwuity. This leads to a fallback to silent notifications. This is documented in several places:

I’ve explained the mechanism in #1533 (comment).

Currently, I am not aware of any bugs resulting from the missing handling of $LAZY, but there may be some.

If I understand correctly, MSC3575 is deprecated in favor of MSC4186, where $ME and $LAZY are no longer present (see also this comment). However, the Rust SDK still seems to rely on them (see here) and Synapse uses them too (see this file, where $ME is StateValues.ME and $LAZY is StateValues.LAZY). I am not very familiar with the Matrix specification or its development process, so this is somewhat confusing to me.

At the moment, however, they still seem to be required, since implementing support for $ME has been confirmed to fix the silent notification bug with Element X.

As described in ~[MSC3575](https://github.com/matrix-org/matrix-spec-proposals/blob/kegan/sync-v3/proposals/3575-sync.md#room-list-parameters)~ [EDIT: previous versions of [MSC4186](https://github.com/matrix-org/matrix-spec-proposals/blob/1786eeb7fd055b8757f51cb8c19904dd5b293891/proposals/4186-simplified-sliding-sync.md#special-values) that are still in use by other homeservers like Synapse and Tuwunel, see comment below], `*`, `$ME` and `$LAZY` in `required_state` are special sentinel values that Continuwuity must resolve. However, `$ME` and `$LAZY` are currently not handled in [`collect_required_state`](https://forgejo.ellis.link/continuwuation/continuwuity/src/commit/eccdb285b8d2b85543095d870c39ec9959201b6c/src/api/client/sync/v5.rs#L684) in `src/api/client/sync/v5.rs`. Only `*` is considered there. Some clients, especially those relying on the official [Matrix Rust SDK](https://github.com/matrix-org/matrix-rust-sdk/), expect these values to be resolved. For example, Element X (iOS and Android), which uses it, fails to load the push rules because `$ME` is not handled correctly by Continuwuity. This leads to a fallback to silent notifications. This is documented in several places: - #1533 - #1424 - https://github.com/element-hq/element-x-ios/issues/5132 I’ve explained the mechanism in https://forgejo.ellis.link/continuwuation/continuwuity/issues/1533#issuecomment-27062. Currently, I am not aware of any bugs resulting from the missing handling of `$LAZY`, but there may be some. ~If I understand correctly, MSC3575 is deprecated in favor of [MSC4186](https://github.com/matrix-org/matrix-spec-proposals/blob/erikj/sss/proposals/4186-simplified-sliding-sync.md), where `$ME` and `$LAZY` are no longer present (see also [this](https://github.com/matrix-org/matrix-spec-proposals/pull/4186#discussion_r2421736069) comment). However, the Rust SDK still seems to rely on them (see [here](https://github.com/matrix-org/matrix-rust-sdk/blob/9d39e4bae8003a349825f15f87123bb8a8096f2e/crates/matrix-sdk-ui/src/notification_client.rs#L499)) and Synapse uses them too (see this [file](https://github.com/element-hq/synapse/blob/bed00bb7669d2768a7e13715bc89b5c34670225f/synapse/handlers/sliding_sync/__init__.py), where `$ME` is `StateValues.ME` and `$LAZY` is `StateValues.LAZY`). I am not very familiar with the Matrix specification or its development process, so this is somewhat confusing to me.~ ~At the moment, however, they still seem to be required, since implementing support for `$ME` has been [confirmed](https://github.com/element-hq/element-x-ios/issues/5132#issuecomment-4230001081) to fix the silent notification bug with Element X.~

nice, hope it would get fixed soon 👍

nice, hope it would get fixed soon 👍
kiorul changed title from Sync v5: $ME and $LAZY in required_state are not resolved to Sync: $ME and $LAZY in required_state are not resolved 2026-04-15 13:35:04 +00:00
Author

Wanted to add that $ME and $LAZY were part of MSC4186 (simplified sliding sync) some months ago (here), removed in this commit. So they aren’t exclusive to MSC3575 (legacy sliding sync). The new boolean lazy_members is not used by Continuwuity either (did not find it in code).

Wanted to add that `$ME` and `$LAZY` were part of MSC4186 (simplified sliding sync) some months ago ([here](https://github.com/matrix-org/matrix-spec-proposals/blob/1786eeb7fd055b8757f51cb8c19904dd5b293891/proposals/4186-simplified-sliding-sync.md)), removed in [this](https://github.com/matrix-org/matrix-spec-proposals/commit/d156cb97fd8f731d4cdfa86a56618c6285899677) commit. So they aren’t exclusive to MSC3575 (legacy sliding sync). The new boolean `lazy_members` is not used by Continuwuity either (did not find it in code).
Author

Just for reference, this (lines 194-256) is how Tuwunel does this. And see this file for Synapse, where $ME is StateValues.ME and $LAZY is StateValues.LAZY).

Just for reference, [this](https://github.com/matrix-construct/tuwunel/blob/00030dca61d72b38b3ed0ebaa89caf5d1d7f15a1/src/api/client/sync/v5/rooms.rs#L194) (lines 194-256) is how Tuwunel does this. And see this [file](https://github.com/element-hq/synapse/blob/bed00bb7669d2768a7e13715bc89b5c34670225f/synapse/handlers/sliding_sync/__init__.py) for Synapse, where `$ME` is `StateValues.ME` and `$LAZY` is `StateValues.LAZY`).
Owner

Actually, I'm not convinced we should implement an older version of the proposal, especially when we're already behind and struggling to catch up. To me, that implies the implementations affected by the lack of these sentinel values should be updated instead

Actually, I'm not convinced we should implement an older version of the proposal, especially when we're already behind and struggling to catch up. To me, that implies the implementations affected by the lack of these sentinel values should be *updated* instead

Hey @nex, fair enough about not chasing the old MSC versions, but I'd push back on the framing here

$ME and $LAZY aren't really "old proposal" — they're what Synapse, Tuwunel, and the Matrix Rust SDK currently implement and
depend on. MSC4186 is still an unmerged pr (https://github.com/matrix-org/matrix-spec-proposals/pull/4186), so "the latest revision" isn't a stable target anyone else is tracking yet. Until the SDK + Synapse drop them, a server that doesn't resolve them is the odd one out, not the conformant one

The "update the implementations instead" path means coordinated changes across matrix-rust-sdk, Element X iOS, Element X
Android, plus a release cycle and user upgrades — months of work behind multiple maintainers we don't control. The
server-side fix is ~15 lines (kiorul already wrote the $ME part) and fix the issue the moment you merge it

Also: this isn't a neutral wait. peoples are really not having notifications working on element X, and since it's the "main client" it's quite bad :/ (to my eyes at least)

Implementing the sentinels also isn't a commitment to an old proposal — it's a compat shim. The server can resolve $ME and
accept literal user IDs; clients that move to the newer format keep working. Forward-compat is preserved, you just stop
breaking the dominant client today.

If the long-term goal is to push the SDK toward MSC4186-latest, for me the right place to make that argument is a matrix-rust-sdk
issue in parallel of having the fix in c10y, not by blocking the server fix users are hitting right now.

Hey @nex, fair enough about not chasing the old MSC versions, but I'd push back on the framing here $ME and $LAZY aren't really "old proposal" — they're what Synapse, Tuwunel, and the Matrix Rust SDK currently implement and depend on. MSC4186 is still an unmerged pr (https://github.com/matrix-org/matrix-spec-proposals/pull/4186), so "the latest revision" isn't a stable target anyone else is tracking yet. Until the SDK + Synapse drop them, a server that doesn't resolve them is the odd one out, not the conformant one The "update the implementations instead" path means coordinated changes across matrix-rust-sdk, Element X iOS, Element X Android, plus a release cycle and user upgrades — months of work behind multiple maintainers we don't control. The server-side fix is ~15 lines (kiorul already wrote the $ME part) and fix the issue the moment you merge it Also: this isn't a neutral wait. peoples are really not having notifications working on element X, and since it's the "main client" it's quite bad :/ (to my eyes at least) Implementing the sentinels also isn't a commitment to an old proposal — it's a compat shim. The server can resolve $ME and accept literal user IDs; clients that move to the newer format keep working. Forward-compat is preserved, you just stop breaking the dominant client today. If the long-term goal is to push the SDK toward MSC4186-latest, for me the right place to make that argument is a matrix-rust-sdk issue in parallel of having the fix in c10y, not by blocking the server fix users are hitting right now.
Owner

$ME and $LAZY aren't really "old proposal" — they're what Synapse, Tuwunel, and the Matrix Rust SDK currently implement and
depend on.

Right, but they aren't in the current proposal anymore. They were removed, those implementations are just behind.

Until the SDK + Synapse drop them, a server that doesn't resolve them is the odd one out, not the conformant one

I don't like the implication that the rust sdk and synapse get to dictate the spec and even what version of proposals are implemented. If you want Synapse behaviour, use Synapse.

The "update the implementations instead" path means coordinated changes across matrix-rust-sdk, Element X iOS, Element X
Android, plus a release cycle and user upgrades.

Correct? That doesn't sound like our problem.

months of work behind multiple maintainers we don't control. The server-side fix is ~15 lines (kiorul already wrote the $ME part) and fix the issue the moment you merge it

We then have to remember to remove this compatibility function when everyone else has caught up, which, as I've stated before, we don't have time to do. If other implementations are behind, that's not our problem - people make it out problem when we're behind, so I don't see why this is different.

Implementing the sentinels also isn't a commitment to an old proposal — it's a compat shim. The server can resolve $ME and
accept literal user IDs; clients that move to the newer format keep working. Forward-compat is preserved, you just stop
breaking the dominant client today.

Implementing anything is a committment. If the dominant client is broken because of us not supporting something that doesn't exist anymore, they can have us sign a contract and we'll gladly fix it. They're paid to be fixing this problem, we aren't. I also don't give a toss what the "dominant" client is, in the same way I also don't care what the "flagship" or "reference" implementations are. The spec is the spec, I follow the documents, not other implementations. It's a very slippery slope that I am personally sick of seeing in the ecosystem and striving to course-correct on.

If the long-term goal is to push the SDK toward MSC4186-latest, for me the right place to make that argument is a matrix-rust-sdk issue in parallel of having the fix in c10y, not by blocking the server fix users are hitting right now.

Feel free to open an issue on their repo for being non-complaint, but we shouldn't be implementing legacy versions of a proposal that is still rapidly iterating. This is firmly not a continuwuity problem.

> $ME and $LAZY aren't really "old proposal" — they're what Synapse, Tuwunel, and the Matrix Rust SDK currently implement and depend on. Right, but they aren't in the current proposal anymore. They were *removed*, those implementations are just behind. > Until the SDK + Synapse drop them, a server that doesn't resolve them is the odd one out, not the conformant one I don't like the implication that the rust sdk and synapse get to dictate the spec and even what version of proposals are implemented. If you want Synapse behaviour, use Synapse. > The "update the implementations instead" path means coordinated changes across matrix-rust-sdk, Element X iOS, Element X Android, plus a release cycle and user upgrades. Correct? That doesn't sound like our problem. > months of work behind multiple maintainers we don't control. The server-side fix is ~15 lines (kiorul already wrote the $ME part) and fix the issue the moment you merge it We then have to remember to remove this compatibility function when everyone else has caught up, which, as I've stated before, we don't have time to do. If other implementations are behind, that's not our problem - people make it out problem when *we're* behind, so I don't see why this is different. > Implementing the sentinels also isn't a commitment to an old proposal — it's a compat shim. The server can resolve $ME and accept literal user IDs; clients that move to the newer format keep working. Forward-compat is preserved, you just stop breaking the dominant client today. Implementing *anything* is a committment. If the dominant client is broken because of us not supporting something that doesn't exist anymore, they can have us sign a contract and we'll gladly fix it. They're *paid* to be fixing this problem, we aren't. I also don't give a toss what the "dominant" client is, in the same way I also don't care what the "flagship" or "reference" implementations are. The spec is the spec, I follow the documents, not other implementations. It's a *very* slippery slope that I am personally sick of seeing in the ecosystem and striving to course-correct on. > If the long-term goal is to push the SDK toward MSC4186-latest, for me the right place to make that argument is a matrix-rust-sdk issue in parallel of having the fix in c10y, not by blocking the server fix users are hitting right now. Feel free to open an issue on their repo for being non-complaint, but we shouldn't be implementing legacy versions of a proposal that is still rapidly iterating. This is firmly *not* a continuwuity problem.
Owner

Side note, please don't use AI for communication on the issue tracker.

Side note, please don't use AI for communication on the issue tracker.
Member

This should probably be closed, as its not a Continuwuity issue, right?

This should probably be closed, as its not a Continuwuity issue, right?
Owner
Yeah, https://github.com/matrix-org/matrix-rust-sdk/issues/6549
Jade closed this issue 2026-05-09 21:54:11 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
5 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
continuwuation/continuwuity#1661
No description provided.