fix(federation): Name the cause when invite state uses stripped events #2111

Closed
mmaudet wants to merge 3 commits from mmaudet/continuwuity:fix/invite-legacy-stripped-state-error into main
Contributor

This pull request makes Continuwuity say why it rejects a federated invite whose
invite_room_state still carries pre-v1.16 stripped state, rather than reporting it as a
malformed PDU.

Since v26.6.1 Continuwuity enforces the Matrix 1.16 requirement that entries of
invite_room_state be full PDUs (MSC4311). Servers which have not migrated yet — Synapse among
them, see element-hq/synapse#19723 — have every one of their invites refused with
400 M_INVALID_PARAM: PDU in invite state (index 0) violates the room event format. That message
names neither the cause nor the sending server, and the only hint, Invite state event is not a PDU, is emitted at debug level, so nothing at all is visible in a default deployment. The
practical effect is that operators cannot tell this apart from a genuinely corrupt event: #2078 and
#2084 were filed three days apart, both duplicates of #1971, and both had to be triaged by hand.

This distinguishes the stripped-state case from a generally malformed entry. The error returned
over federation now states that the entry is a stripped state event, that Matrix 1.16 requires full
PDUs, and that the sending server needs updating; the rejection is logged at warn level with the
origin server and the room. Synapse already relays the remote server's error text to the inviting
user on this path — verified against Synapse 1.158.0 — so this is what that user reads today, not
after some future change.
A troubleshooting entry documents the symptom so that the next operator to hit it can find it
without opening an issue.

Behaviour is unchanged: the same invites are accepted and refused as before, with the same error
code.

Pull request checklist:

  • This pull request targets the main branch, and the branch is named something other than
    main.
  • I have written an appropriate pull request title and my description is clear.
  • I understand I am responsible for the contents of this pull request.
  • I have followed the contributing guidelines:
<!-- In order to help reviewers know what your pull request does at a glance, you should ensure that 1. Your PR title is a short, single sentence describing what you changed 2. You have described in more detail what you have changed, why you have changed it, what the intended effect is, and why you think this will be beneficial to the project. If you have made any potentially strange/questionable design choices, but didn't feel they'd benefit from code comments, please don't mention them here - after opening your pull request, go to "files changed", and click on the "+" symbol in the line number gutter, and attach comments to the lines that you think would benefit from some clarification. --> This pull request makes Continuwuity say *why* it rejects a federated invite whose `invite_room_state` still carries pre-v1.16 stripped state, rather than reporting it as a malformed PDU. Since v26.6.1 Continuwuity enforces the Matrix 1.16 requirement that entries of `invite_room_state` be full PDUs (MSC4311). Servers which have not migrated yet — Synapse among them, see element-hq/synapse#19723 — have every one of their invites refused with `400 M_INVALID_PARAM: PDU in invite state (index 0) violates the room event format`. That message names neither the cause nor the sending server, and the only hint, `Invite state event is not a PDU`, is emitted at debug level, so nothing at all is visible in a default deployment. The practical effect is that operators cannot tell this apart from a genuinely corrupt event: #2078 and #2084 were filed three days apart, both duplicates of #1971, and both had to be triaged by hand. This distinguishes the stripped-state case from a generally malformed entry. The error returned over federation now states that the entry is a stripped state event, that Matrix 1.16 requires full PDUs, and that the sending server needs updating; the rejection is logged at `warn` level with the origin server and the room. Synapse already relays the remote server's error text to the inviting user on this path — verified against Synapse 1.158.0 — so this is what that user reads today, not after some future change. A troubleshooting entry documents the symptom so that the next operator to hit it can find it without opening an issue. Behaviour is unchanged: the same invites are accepted and refused as before, with the same error code. <!-- Example: This pull request allows us to warp through time and space ten times faster than before by double-inverting the warp drive with hyperheated jump fluid, both making the drive faster and more efficient. This resolves the common issue where we have to wait more than 10 milliseconds to engage, use, and disengage the warp drive when travelling between galaxies. --> <!-- Closes: #... --> <!-- Fixes: #... --> <!-- Uncomment the above line(s) if your pull request fixes an issue or closes another pull request by superseding it. Replace `#...` with the issue/pr number, such as `#123`. --> **Pull request checklist:** <!-- You need to complete these before your PR can be considered. If you aren't sure about some, feel free to ask for clarification in #dev:continuwuity.org. --> - [x] This pull request targets the `main` branch, and the branch is named something other than `main`. - [x] I have written an appropriate pull request title and my description is clear. - [x] I understand I am responsible for the contents of this pull request. - I have followed the [contributing guidelines][c1]: - [x] My contribution follows the [code style][c2], if applicable. - [x] I ran [pre-commit checks][c1pc] before opening/drafting this pull request. - [x] I have [tested my contribution][c1t] (or proof-read it for documentation-only changes) myself, if applicable. This includes ensuring code compiles. - [x] My commit messages follow the [commit message format][c1cm] and are descriptive. <!-- Notes on these requirements: - While not required, we encourage you to sign your commits with GPG or SSH to attest the authenticity of your changes. - While we allow LLM-assisted contributions, we do not appreciate contributions that are low quality, which is typical of machine-generated contributions that have not had a lot of love and care from a human. Please do not open a PR if all you have done is asked ChatGPT to tidy up the codebase with a +-100,000 diff. - In the case of code style violations, reviewers may leave review comments/change requests indicating what the ideal change would look like. For example, a reviewer may suggest you lower a log level, or use `match` instead of `if/else` etc. - In the case of code style violations, pre-commit check failures, minor things like typos/spelling errors, and in some cases commit format violations, reviewers may modify your branch directly, typically by making changes and adding a commit. Particularly in the latter case, a reviewer may rebase your commits to squash "spammy" ones (like "fix", "fix", "actually fix"), and reword commit messages that don't satisfy the format. - Pull requests MUST pass the `Checks` CI workflows to be capable of being merged. This can only be bypassed in exceptional circumstances. If your CI flakes, let us know in matrix:r/dev:continuwuity.org. - Pull requests have to be based on the latest `main` commit before being merged. If the main branch changes while you're making your changes, you should make sure you rebase on main before opening a PR. Your branch will be rebased on main before it is merged if it has fallen behind. - We typically only do fast-forward merges, so your entire commit log will be included. Once in main, it's difficult to get out cleanly, so put on your best dress, smile for the cameras! --> [c1]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md [c2]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/docs/development/code_style.mdx [c1pc]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md#pre-commit-checks [c1t]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md#running-tests-locally [c1cm]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md#commit-messages
An invite whose invite_room_state still uses pre-v1.16 stripped state was
rejected as though the entry were a malformed PDU, and the only diagnosis
was a debug-level log line. Distinguish the two cases: say that the entry
is a stripped state event and that Matrix 1.16 requires full PDUs, and log
the rejection at warn level with the origin server.
Two duplicate reports of this were filed within three days of each other.
chore: Add changelog news fragment
Some checks failed
Auto Labeler / Apply labels based on changed files (pull_request_target) Successful in 3s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Has been cancelled
Checks / Prek / Pre-commit & Formatting (pull_request) Has been cancelled
Checks / Prek / Check changed files (pull_request) Has been cancelled
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
042544a268
mmaudet force-pushed fix/invite-legacy-stripped-state-error from 042544a268
Some checks failed
Auto Labeler / Apply labels based on changed files (pull_request_target) Successful in 3s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Has been cancelled
Checks / Prek / Pre-commit & Formatting (pull_request) Has been cancelled
Checks / Prek / Check changed files (pull_request) Has been cancelled
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
to cd7cfc8faf
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Has been cancelled
Checks / Prek / Pre-commit & Formatting (pull_request) Has been cancelled
Checks / Prek / Check changed files (pull_request) Has been cancelled
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
2026-08-07 06:08:04 +00:00
Compare
Owner

This is deliberate - only noncompliant servers will send malformed data, and stripped state is malformed data. The error is correct, the received events are not PDUs, and thus they fail the room format check. There's no reason to distinguish stripped state because as far as this endpoint is concerned, there's no such thing as stripped state. Spec v1.16 was released a year ago, we've already ripped the bandaid off so there's no point attempting to retroactively compensate for compatibility issues.
There's also no need for this to emit a log visible in the console. If someone can't receive an invite, so far empirically they'll be painfully aware of this fact.

I'm inclined to reject this PR unless someone else on the team believes otherwise (cc @Jade @ginger)

This is deliberate - only noncompliant servers will send malformed data, and stripped state *is* malformed data. The error is correct, the received events are not PDUs, and thus they fail the room format check. There's no reason to distinguish stripped state because as far as this endpoint is concerned, there's no such thing as stripped state. Spec v1.16 was released a year ago, we've already ripped the bandaid off so there's no point attempting to retroactively compensate for compatibility issues. There's also no need for this to emit a log visible in the console. If someone can't receive an invite, so far empirically they'll be painfully aware of this fact. I'm inclined to reject this PR unless someone else on the team believes otherwise (cc @Jade @ginger)
Owner

I mean, a prompt for other servers to upgrade isn't a bad thing imo?

I mean, a prompt for other servers to upgrade isn't a bad thing imo?
Owner

@Jade wrote in #2111 (comment):

I mean, a prompt for other servers to upgrade isn't a bad thing imo?

I just don't see the need to special case it. There's also no guarantee the error message will be passed back to a user who can even do anything about it

@Jade wrote in https://forgejo.ellis.link/continuwuation/continuwuity/pulls/2111#issuecomment-33877: > I mean, a prompt for other servers to upgrade isn't a bad thing imo? I just don't see the need to special case it. There's also no guarantee the error message will be passed back to a user who can even do anything about it
mmaudet closed this pull request 2026-08-07 10:23:03 +00:00
Author
Contributor

Some context, in case it helps to clarify my point.

I'm building an application on top of Continuwuity where federation is a hard requirement, so I test interop with Synapse in both directions. Continuwuity → Synapse works end to end: invite, join, encrypted messages readable on both sides. The reverse direction is entirely blocked : Continuwuity refuses every invite originating from Synapse, in every room version we tried (6 through 12):
400 M_INVALID_PARAM: PDU in invite state (index 0) violates the room event format

The rejection itself is correct and deliberate; what cost us was that the message names nothing. It reads as "your event is malformed", so the first hypotheses are a Continuwuity bug or a corrupt event, and the only real hint sits at debug level, invisible in a default deployment. It took a full campaign across all room versions to establish that the cause was on the sending side, not ours.

With the wording proposed here, that same developer reads that the peer is still sending pre-1.16 stripped state and that the peer is what needs updating. That is the difference between a dead end and something actionable: rather than filing a third duplicate here (#2078, #2084, both of #1971), they can carry it to where the fix actually lives (element-hq/synapse#19723). In practice the error string is the only channel by which that information reaches someone able to act on it.

Some context, in case it helps to clarify my point. I'm building an application on top of Continuwuity where federation is a hard requirement, so I test interop with Synapse in both directions. Continuwuity → Synapse works end to end: invite, join, encrypted messages readable on both sides. The reverse direction is entirely blocked : Continuwuity refuses every invite originating from Synapse, in every room version we tried (6 through 12): 400 M_INVALID_PARAM: PDU in invite state (index 0) violates the room event format The rejection itself is correct and deliberate; what cost us was that the message names nothing. It reads as "your event is malformed", so the first hypotheses are a Continuwuity bug or a corrupt event, and the only real hint sits at debug level, invisible in a default deployment. It took a full campaign across all room versions to establish that the cause was on the sending side, not ours. With the wording proposed here, that same developer reads that the peer is still sending pre-1.16 stripped state and that the peer is what needs updating. That is the difference between a dead end and something actionable: rather than filing a third duplicate here (#2078, #2084, both of #1971), they can carry it to where the fix actually lives ([element-hq/synapse#19723](https://github.com/element-hq/synapse/pull/19723)). In practice the error string is the only channel by which that information reaches someone able to act on it.
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 7s
Required
Details
Documentation / Build and Deploy Documentation (pull_request) Has been cancelled
Checks / Prek / Pre-commit & Formatting (pull_request) Has been cancelled
Required
Details
Checks / Prek / Check changed files (pull_request) Has been cancelled
Required
Details
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
Required
Details

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
3 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!2111
No description provided.