Skip to content
Open
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
bdfeb90
Client side API's should still use stripped events with MSC4311
MadLittleMods Apr 23, 2026
43a11f5
Add changelog
MadLittleMods Apr 23, 2026
7f25120
Merge branch 'develop' into madlittlemods/remove-flawed-msc4311-parti…
MadLittleMods May 1, 2026
6026aaa
Non-working: Use full PDU's for `invite_room_state` in federation
MadLittleMods May 2, 2026
e0eb224
Iteration that uses current state
MadLittleMods May 2, 2026
3464ec8
Use `get_stripped_room_state_ids_from_event_context`
MadLittleMods May 2, 2026
f96c008
Invite event should be stripped when included in `invite_state`
MadLittleMods May 4, 2026
a088aa8
Sanitize `invite_room_state` received over federation
MadLittleMods May 4, 2026
336b686
Fix test lints
MadLittleMods May 4, 2026
22f4f20
Updated comment
MadLittleMods May 4, 2026
cce5dc7
Merge branch 'develop' into madlittlemods/remove-flawed-msc4311-parti…
MadLittleMods May 21, 2026
7e379e7
Make the TODO more obvious
MadLittleMods May 21, 2026
92d0d8b
Placeholder arg docstring
MadLittleMods May 21, 2026
76b4905
Better logic/reasoning
MadLittleMods May 22, 2026
5103f1b
Better comment flow
MadLittleMods May 22, 2026
5c1f4ca
Use `FIXME(MSC4311)` prefix
MadLittleMods May 22, 2026
374c4c5
Mark down create event after we verify it's valid
MadLittleMods May 22, 2026
ffe5c4b
Small comment to explain (we also explain above)
MadLittleMods May 22, 2026
2b900b4
Better `invite_room_state` scrutiny
MadLittleMods May 22, 2026
5e12cb8
Fix `events` typo
MadLittleMods May 22, 2026
ff533df
Event ID context
MadLittleMods May 22, 2026
de78d9e
Simplify logic to just use `hs.config.api.room_prejoin_state` instead…
MadLittleMods May 22, 2026
4598a43
`_parse_stripped_room_state`
MadLittleMods May 23, 2026
fbff685
`_minimal_parse_stripped_room_state`
MadLittleMods May 23, 2026
75a53ef
Strip the knock itself we add down `/sync`
MadLittleMods May 23, 2026
178dd89
Merge branch 'develop' into madlittlemods/remove-flawed-msc4311-parti…
MadLittleMods May 26, 2026
1926534
Account for previous Matrix versions where `invite_room_state` is opt…
MadLittleMods May 26, 2026
17c3763
Better `msc4311_stripped_state` description
MadLittleMods May 26, 2026
75d1935
The PDU's over federation can be full PDU's now
MadLittleMods May 26, 2026
3888387
Raise 500 when federation returns 400 `M_MISSING_PARAM`
MadLittleMods May 26, 2026
259f151
Add note about future Complement tests
MadLittleMods May 26, 2026
c289e93
Kick CI after Sytest fixes
MadLittleMods May 27, 2026
ec572c6
Merge branch 'develop' into madlittlemods/remove-flawed-msc4311-parti…
MadLittleMods May 27, 2026
4e7f3fc
Merge branch 'develop' into madlittlemods/remove-flawed-msc4311-parti…
MadLittleMods Jul 9, 2026
bf9ab2f
Refactor to include `inviter_user_id` as part of stripped state
MadLittleMods Jul 9, 2026
c54c93b
Just pass in the event
MadLittleMods Jul 9, 2026
17a4ef6
Remove `_calculate_stripped_state_filter`
MadLittleMods Jul 9, 2026
1cf8282
Update date that Synapse is compliant
MadLittleMods Jul 9, 2026
ce17c93
Cross-link #19943
MadLittleMods Jul 9, 2026
5cc8753
Fix `compatibility` typo
MadLittleMods Jul 9, 2026
53a68d7
Use correct `knock_room_state` reference from response
MadLittleMods Jul 9, 2026
7488a24
Use full PDU's for v1 of federation invite API
MadLittleMods Jul 9, 2026
3870034
Fix typo causing extra nesting
MadLittleMods Jul 10, 2026
40d1316
Kick CI after deleting sytest branch with same name
MadLittleMods Jul 10, 2026
3fc94ba
Fix arg ordering typo with `SynapseError`
MadLittleMods Jul 10, 2026
26bf739
Cross-link MSC4319
MadLittleMods Jul 22, 2026
2822f3c
Move parse/serialize as methods of `StrippedStateEvent`
MadLittleMods Jul 28, 2026
3ce6900
Rename `parse` to `from_json_dict`
MadLittleMods Jul 28, 2026
19d8a7a
Rename `serialize` to `as_json_dict`
MadLittleMods Jul 28, 2026
ecab104
Fix `builtins.TypeError: unsupported operand type(s) for |: 'str' and…
MadLittleMods Jul 28, 2026
eed3071
MSC4319 is now merged
MadLittleMods Jul 28, 2026
f751b5f
Merge branch 'develop' into madlittlemods/remove-flawed-msc4311-parti…
MadLittleMods Jul 28, 2026
e06b311
Merge branch 'develop' into madlittlemods/remove-flawed-msc4311-parti…
MadLittleMods Jul 29, 2026
e301cdd
Start error off more plainly: `The other user's server did not unders…
MadLittleMods Jul 29, 2026
bc73bb0
Merge branch 'develop' into madlittlemods/remove-flawed-msc4311-parti…
MadLittleMods Aug 3, 2026
0baa67b
Merge branch 'develop' into madlittlemods/remove-flawed-msc4311-parti…
MadLittleMods Aug 3, 2026
4f70688
Iterate on error
MadLittleMods Aug 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/19723.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Remove flawed [MSC4311](https://github.com/matrix-org/matrix-spec-proposals/pull/4311) partial implementation: Client-side API's like `/sync` should still use stripped events.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Complement tests are expected to fail ❌ as we removed the flawed partial implementation in this PR.

The Complement tests have been updated in matrix-org/complement#796 and pass locally. We will merge both PRs at the same time.

Comment thread
MadLittleMods marked this conversation as resolved.
19 changes: 19 additions & 0 deletions rust/src/room_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,23 @@ pub struct RoomVersion {
/// This is similar to how doubly-linked lists can potentially not refer to previous items correctly
/// without verifying the list's integrity, but doing it on every insert is too expensive.
pub msc4242_state_dags: bool,
/// Determines whether a room version *SHOULD* rather than *MAY* reject invites/knocks
/// with invalid stripped state events.
///
/// According to MSC4311:
/// > If any of the [stripped state] events are not a PDU, not for the room ID specified, or fail
/// > signature checks, or the `m.room.create` event is missing, the receiving
/// > server MAY respond to invites with a `400 M_MISSING_PARAM` standard Matrix
/// > error (new to the endpoint). For invites to room version 12+ rooms, servers
/// > SHOULD rather than MAY respond to such requests with `400 M_MISSING_PARAM`.
///
/// Regardless of room version (we should always do these things):
/// 1. The `m.room.create` event *MUST* be included in
/// `invite_room_state`/`knock_room_state` when sending invites/knocks over the
/// federation API's.
/// 2. Use full PDU's in the `invite_room_state`/`knock_room_state` in the federation
/// API. The client API still uses stripped state.
msc4311_stripped_state: bool,
}

impl RoomVersion {
Expand All @@ -187,6 +204,7 @@ impl RoomVersion {
msc4291_room_ids_as_hashes: false,
strict_event_byte_limits_room_versions: false,
msc4242_state_dags: false,
msc4311_stripped_state: false,
};

pub const V2: RoomVersion = RoomVersion {
Expand Down Expand Up @@ -304,6 +322,7 @@ impl RoomVersion {
state_res: StateResolutionVersions::V2_1,
msc4289_creator_power_enabled: true,
msc4291_room_ids_as_hashes: true,
msc4311_stripped_state: true,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this not break invites across new and old Synapses for v12 rooms?

@MadLittleMods MadLittleMods Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How so? We don't strictly validate anything (just warn when it fails validation in v12 rooms).

See "What does this PR do?" in the PR description.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, my bad. Feels very odd to have an option that merely causes things to log. Especially given that initially this will log for almost every invite in v12. I wonder if its worth it for now?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's house-keeping for the room versions. We use it today and will use it in the future.

..Self::V11
};

Expand Down
40 changes: 40 additions & 0 deletions synapse/events/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,46 @@ class StrippedStateEvent:
sender: str
content: dict[str, Any]

def as_json_dict(self) -> JsonDict:
"""
Serialize to the JSON representation of 'Stripped State' according to the Matrix
spec
"""

return {
"type": self.type,
"state_key": self.state_key,
"sender": self.sender,
"content": self.content,
}

@staticmethod
def from_json_dict(raw_stripped_event: JsonDict) -> "StrippedStateEvent | None":
"""
Given a raw value from an event's `unsigned` field, attempt to parse it into a
`StrippedStateEvent`.
"""
if isinstance(raw_stripped_event, dict):
# All of these fields are required
type = raw_stripped_event.get("type")
state_key = raw_stripped_event.get("state_key")
sender = raw_stripped_event.get("sender")
content = raw_stripped_event.get("content")
if (
isinstance(type, str)
and isinstance(state_key, str)
and isinstance(sender, str)
and isinstance(content, dict)
):
return StrippedStateEvent(
type=type,
state_key=state_key,
sender=sender,
content=content,
)

return None


@attr.s(slots=True, frozen=True, auto_attribs=True)
class EventMetadata:
Expand Down
39 changes: 1 addition & 38 deletions synapse/events/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
CANONICALJSON_MAX_INT,
CANONICALJSON_MIN_INT,
MAX_PDU_SIZE,
EventTypes,
)
from synapse.api.errors import Codes, SynapseError
from synapse.logging.opentracing import SynapseTags, set_tag, trace
Expand All @@ -55,7 +54,7 @@
from synapse.synapse_rust.types import Requester
from synapse.types import JsonDict

from . import EventBase, StrippedStateEvent
from . import EventBase

# These are imported only to re-export them (callers import them from this
# module); listing them in __all__ stops the unused-import lint flagging them
Expand Down Expand Up @@ -549,45 +548,9 @@ def strip_event(event: EventBase) -> JsonDict:
Stripped state events can only have the `sender`, `type`, `state_key` and `content`
properties present.
"""
# MSC4311: Ensure the create event is available on invites and knocks.
# TODO: Implement the rest of MSC4311
if (
event.room_version.msc4291_room_ids_as_hashes
and event.type == EventTypes.Create
and event.get_state_key() == ""
):
return event.get_pdu_json()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the flawed MSC4311 partial implementation

return {
"type": event.type,
"state_key": event.state_key,
"content": dict(event.content),
"sender": event.sender,
}


def parse_stripped_state_event(raw_stripped_event: Any) -> StrippedStateEvent | None:
"""
Given a raw value from an event's `unsigned` field, attempt to parse it into a
`StrippedStateEvent`.
"""
if isinstance(raw_stripped_event, dict):
# All of these fields are required
type = raw_stripped_event.get("type")
state_key = raw_stripped_event.get("state_key")
sender = raw_stripped_event.get("sender")
content = raw_stripped_event.get("content")
if (
isinstance(type, str)
and isinstance(state_key, str)
and isinstance(sender, str)
and isinstance(content, dict)
):
return StrippedStateEvent(
type=type,
state_key=state_key,
sender=sender,
content=content,
)

return None
112 changes: 101 additions & 11 deletions synapse/federation/federation_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import itertools
import logging
from http import HTTPStatus
from typing import (
TYPE_CHECKING,
AbstractSet,
Expand Down Expand Up @@ -59,6 +60,7 @@
RoomVersions,
)
from synapse.events import EventBase, builder, make_event_from_dict
from synapse.events.snapshot import EventContext
from synapse.federation.federation_base import (
FederationBase,
InvalidEventSignatureError,
Expand All @@ -70,7 +72,12 @@
from synapse.http.types import QueryParams
from synapse.logging.opentracing import SynapseTags, log_kv, set_tag, tag_args, trace
from synapse.metrics import SERVER_NAME_LABEL
from synapse.types import JsonDict, StrCollection, UserID, get_domain_from_id
from synapse.types import (
JsonDict,
StrCollection,
UserID,
get_domain_from_id,
)
from synapse.util.async_helpers import concurrently_execute
from synapse.util.caches.expiringcache import ExpiringCache
from synapse.util.duration import Duration
Expand Down Expand Up @@ -1303,12 +1310,12 @@ async def send_invite(
self,
destination: str,
room_id: str,
event_id: str,
pdu: EventBase,
context: EventContext,
) -> EventBase:
room_version = await self.store.get_room_version(room_id)

content = await self._do_send_invite(destination, pdu, room_version)
content = await self._do_send_invite(destination, pdu, context, room_version)

pdu_dict = content["event"]

Expand All @@ -1329,11 +1336,21 @@ async def send_invite(
return pdu

async def _do_send_invite(
self, destination: str, pdu: EventBase, room_version: RoomVersion
self,
destination: str,
pdu: EventBase,
context: EventContext,
room_version: RoomVersion,
) -> JsonDict:
"""Actually sends the invite, first trying v2 API and falling back to
v1 API if necessary.

Args:
destination:
pdu: Invite event
context:
room_version:

Returns:
The event as a dict as returned by the remote server

Expand All @@ -1344,6 +1361,19 @@ async def _do_send_invite(
"""
time_now = self._clock.time_msec()

# MSC4311: For the federation API, format events in `invite_room_state` as full
# PDU's
#
# Find the full events based on the state at the time of the invite
state_ids = await self.store.get_stripped_room_state_ids_from_event_context(
pdu,
context,
)
state_events = await self.store.get_events(state_ids)
assert set(state_ids) == set(state_events.keys()), (
"We should have all events available that were set as stripped state."
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, this is technically a behaviour change where we are recalculating the stripped state here rather than using the stripped state we calculated at event creation.

Generally, I'm wondering if we should change the format of what we store as invite_room_state in the event json in the DB, rather than having this somewhat weird thing going where we have to recalculate it. Not really sure how tractable it is, but you can imagine a world where we store in a separate table the stripped state event IDs for locally generated events.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤷 Future plans


try:
return await self.transport_layer.send_invite_v2(
destination=destination,
Expand All @@ -1352,7 +1382,11 @@ async def _do_send_invite(
content={
"event": pdu.get_pdu_json(time_now),
"room_version": room_version.identifier,
"invite_room_state": pdu.unsigned.get("invite_room_state", []),
"invite_room_state": [
# Use full PDU's according to MSC4311
state_event.get_pdu_json(time_now)
for state_event in state_events.values()
],
},
)
except HttpResponseException as e:
Expand All @@ -1367,18 +1401,74 @@ async def _do_send_invite(
"User's homeserver does not support this room version",
Codes.UNSUPPORTED_ROOM_VERSION,
)
# MSC4311: The 400 `M_MISSING_PARAM` error SHOULD be translated to a 5xx
# error by the sending server over the Client-Server API. This is done
# because there's nothing the client can materially do differently to make
# the request succeed.
elif (
err.code == HTTPStatus.BAD_REQUEST
and err.errcode == Codes.MISSING_PARAM
):
raise SynapseError(
500,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're not doing a 4xx response then we shouldn't use 500 as it's not an internal server error. I'm not really sure what the closest HTTP code for "this server can't perform the action requested", it's half a 4xx and half a 5xx.

TBH it feels quite similar to the 400 above, "User's homeserver does not support this room version".

@MadLittleMods MadLittleMods Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the comment above states, the MSC tells us this should be a 5xx error.

I chose 500 as the other server is saying our homeserver is doing something wrong.

And the description sounds perfect:

The HTTP 500 Internal Server Error server error response status code indicates that the server encountered an unexpected condition that prevented it from fulfilling the request.

-- https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/500

In other words, our homeserver implementation is preventing the invite from going through. Nothing the user can do.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, bleurgh. The problem is that in practice returning a 500 is surprising behaviour for almost everyone: they expect a 500 to indicate there is a bug/misconfiguration in the server. Clients/users will retry when they hit a 500 as they assume it may be a transient problem.

Generally, regardless of what the web specs imply, clients view 5xx as possibly transient server issues, while 4xx as a final failure. Most 4xx are actually things the user can't do anything about, e.g. 403 or 404.

Concretely: returning a 500 will cause confusion for server operators (and us) as that should be reserved for bugs, and clients will keep retrying this endpoint. Intermediate proxies do sometimes infer uptime via 5xx errors (e.g. returning 502 often causes this).

Have taken this up wit the Spec Core Team.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f"Received {HTTPStatus.BAD_REQUEST} {Codes.MISSING_PARAM} response from remote homeserver "
"while trying to send the invite over federation. This indicates a compatibility problem "
"between your homeserver and the homeserver you're trying to send the invite to "
"(either one could be at fault).",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, missed this last time but I don't think this is a useful user facing error, it's too verbose and technical.

I think one of the following maybe:

Could not send the invite to the user's server.

The user's server rejected the invite.

Your server cannot send invite's to the remote server

We want something that the user can understand the net result: namely the invite failed for some reason.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as a user, not knowing why the invite failed (beyond "computer said no") would be more frustrating than the confusion caused by a technical error that I can ask for help with. As a server admin, it'd be even more annoying because I would then have to open a terminal and scrape through logs to try and find out more information.
Since this is explicitly only caused by an incompatibility, if you want non-technical, I think something more akin to

The user's server did not understand our invite and may be outdated

would make sense. It's simple, concise, but still explains what the problem was, and a possible solution. It's also similar to the error returned when the remote server doesn't support the room version, just above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm in agreeance on providing enough info so that the error is useful to understand and for others (like us when people ask for help).

I've updated the error message to start off more plainly: The other user's server did not understand our invite. [...]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair that we should communicate that it is likely an incompatibility issue.

The other user's server did not understand our invite. [...]

I think this is confusing to people who aren't technical, how can an invite be not "understood"?

The problem is that these are user visible and therefore affect the UX. In practice giving "complicated" error messages simply causes more confusion for the vast majority of users with little benefit (even to technical users). Especially in this case where nothing we're telling the user in the error messages is actually useful information. The fact that the remote server rejected it with a 400 M_MISSING_PARAM is pretty meaningless?

The overarching problem here is that we simply don't know why the other side rejected the invite, and so we can't give a useful error message to the user, just an unsatisfactory "something went went wrong".

I think the information that is useful for the user is:

  1. The invite failed.
  2. It's not the user's fault.
  3. Retrying immediately won't help.

So perhaps something like:

Cannot send the invite to the user's server; it was rejected. (This could be due to a compatibility issue between the servers).

It's not great, but I think says all that is useful to convey in a more friendly language. It's also unique enough that if more information is required server admins can scrape the logs easily.

@MadLittleMods MadLittleMods Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better phrasing is good but we're losing too much information in my opinion.

The problem needs to be clear. Forcing a random user to get their homeserver admin to log dive is not nice. It's undue burden on a homeserver admin and not possible in unresponsive admin scenarios.

If someone posts that error message in Synapse Admins and asks why, my next question is what did the other server respond with? If I looked specifically at the Synapse code, I can deduce it in the this case because it corresponds to one specific scenario but it still requires me to dig. That's just not necessary. Then the next step to look at is the two homeserver versions and see what they're running.

These are the same questions I would have as a user if this happened to me. Knowing that the other server responded with 400 M_MISSING_PARAM is useful to me. It doesn't matter that either my homeserver or the other homeserver needs to change which I don't control.

I've updated to this (separated the simple explanation from the details with \n\n):

f"Invite was rejected by the recipient's server.\n\n"
f"The remote homeserver ({destination}) returned {HTTPStatus.BAD_REQUEST} {Codes.MISSING_PARAM} "
"which indicates a compatibility problem between your homeserver and the "
"homeserver you're trying to send the invite to (either one could be at fault).",

To better illustrate, this is a Hulu error. This drives me crazy :feelsgood:

We're having trouble playing...

Rest assured, we're working on it. In the meantime, it may help if you restart the video.

Need help? Visit help.hulu.com/support in a browser

Hulu Error Code: P-DEV318
05/31/2022 20:14:41 PM PDT

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do agree that we shouldn't return a completely vacuous error. However, we do need to balance utility between super-power users and UX for normal users.

To that end: I don't really see what specifying {HTTPStatus.BAD_REQUEST} {Codes.MISSING_PARAM} in the error response gives users or helps with diagnostics. The proposed error response gives the information needed: one of the two servers is probably out-of-date. If that is not the case then you'll need to dig into the logs anyway to figure out what is wrong, you're not going to be able to tell just by the error codes.

I wouldn't be that adverse to adding extra information if our error messages had an extra collapsed-by-default section for "Advanced Information", but we don't have that.

Plus, generally we're reluctant to give out too much information to users (like stack traces), as they can too easily leak information we'd rather wasn't. At which point for most cases you're going to need to look at the logs anyway. (Not to mention that any remedies here require involvement by the server admins)

@MadLittleMods MadLittleMods Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From your three point criteria: the invite failed, it's not the user's fault, retrying won't help. A vague message asserts those but a specific message demonstrates them. Reassurance without specifics isn't very believable. Everyone has been told "sorry, something went wrong" by a system that was in fact blaming them or hiding the fact that they could have changed the outcome by trying something different. The details help close those loops and let the person stop second-guessing themselves.

The \n\n separation means the details cost the non-technical user nothing as they read the first sentence and stop, which is effectively your ideal way to provide "Advanced Information" anyway.

I think we've struck a good balance with the last iteration.

Codes.UNKNOWN,
additional_fields={
"cause": err.msg,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we have to worry about leaking anything by passing this error message along. Calling this out so the reviewer can sanity check this assumption

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Err, there's little point returning this to clients as nothing will read it. It can also be confusing if devs interpret it as the what this server is complaining about to the client

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #19723 (comment) in regards to providing enough info.

If you can think of a better way to present it, that would be good.

"destination_server": destination,
},
)
else:
raise err

# Didn't work, try v1 API.
# Note the v1 API returns a tuple of `(200, content)`

_, content = await self.transport_layer.send_invite_v1(
destination=destination,
room_id=pdu.room_id,
event_id=pdu.event_id,
content=pdu.get_pdu_json(time_now),
)
try:
# Use full PDU's for `invite_room_state` according to MSC4311
#
# With the v1 invite API, `invite_room_state` is carried inside the event
# instead of a separate field like in v2 so we must munge it in ourselves
event_json = pdu.get_pdu_json(time_now)
event_json.setdefault("unsigned", {})["invite_room_state"] = [
# Use full PDU's according to MSC4311
state_event.get_pdu_json(time_now)
for state_event in state_events.values()
]

_, content = await self.transport_layer.send_invite_v1(
destination=destination,
room_id=pdu.room_id,
event_id=pdu.event_id,
content=event_json,
)
except HttpResponseException as e:
# MSC4311: The 400 `M_MISSING_PARAM` error SHOULD be translated to a 5xx
# error by the sending server over the Client-Server API. This is done
# because there's nothing the client can materially do differently to make
# the request succeed.
err = e.to_synapse_error()
if (
err.code == HTTPStatus.BAD_REQUEST
and err.errcode == Codes.MISSING_PARAM
):
raise SynapseError(
500,
f"Received {HTTPStatus.BAD_REQUEST} {Codes.MISSING_PARAM} response from remote homeserver "
"while trying to send the invite over federation. This indicates a compatibility problem "
"between your homeserver and the homeserver you're trying to send the invite to "
"(either one could be at fault).",
Codes.UNKNOWN,
additional_fields={
"cause": err.msg,
"destination_server": destination,
},
)
else:
raise err
return content

async def send_leave(self, destinations: Iterable[str], pdu: EventBase) -> None:
Expand Down
Loading
Loading