-
Notifications
You must be signed in to change notification settings - Fork 567
Don't 500 /sync when an always-included event has no state #19960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1 @@ | ||||||
| Fix a bug where `/sync` could return a 500 error ("Missing state for event that is not user's own membership") when an out-of-band membership event, since de-outliered into the room's current state, appeared in a room timeline. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Would a better fix be to fix the cache problem? |
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -196,21 +196,17 @@ def allowed(event: EventBase) -> FilteredEvent | None: | |
| # Filter out call invites in public rooms, as this would potentially | ||
| # ring a lot of users. | ||
| if event.type == EventTypes.CallInvite and not event.is_state(): | ||
| # `state_after_event` should only be None if the event is an outlier, | ||
| # and earlier code should filter out outliers entirely. | ||
| # | ||
| # In addition, we only create outliers locally for out-of-band | ||
| # invite rejections, invites received over federation, or state | ||
| # events needed to authorise other events. None of this applies to | ||
| # call invites. | ||
| assert state_after_event is not None | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I checked why fable downgraded the assert into a condition, and:
|
||
|
|
||
| room_join_rules = state_after_event.get((EventTypes.JoinRules, "")) | ||
| if ( | ||
| room_join_rules is not None | ||
| and room_join_rules.content.get("join_rule") == JoinRules.PUBLIC | ||
| ): | ||
| return None | ||
| # `state_after_event` should only be None if the event is an outlier | ||
| # (or our copy of the event is stale and still flagged as one, see | ||
| # below); in either case we can't check the join rules, so let the | ||
| # event through. | ||
| if state_after_event is not None: | ||
| room_join_rules = state_after_event.get((EventTypes.JoinRules, "")) | ||
| if ( | ||
| room_join_rules is not None | ||
| and room_join_rules.content.get("join_rule") == JoinRules.PUBLIC | ||
| ): | ||
| return None | ||
|
|
||
| # Annotate the event with the user's membership after the event. | ||
| # | ||
|
|
@@ -224,8 +220,23 @@ def allowed(event: EventBase) -> FilteredEvent | None: | |
| elif state_after_event is not None: | ||
| user_membership_event = state_after_event.get((EventTypes.Member, user_id)) | ||
| else: | ||
| # unreachable! | ||
| raise Exception("Missing state for event that is not user's own membership") | ||
| # We have no state for this event: it was flagged as an outlier | ||
| # when we fetched the state above, but `always_include_ids` let it | ||
| # through anyway. This can happen when an out-of-band membership | ||
| # event (e.g. an invite, or a rejection of one, received while not | ||
| # in the room) is later de-outliered — because we are also in the | ||
| # room and received it over federation — and enters the current | ||
| # state, while the copy of the event we are working with (e.g. from | ||
| # a worker's not-yet-invalidated cache) still carries the outlier | ||
| # flag. We don't know the user's membership at this point in the | ||
| # DAG, which MSC4115 permits — return the event unannotated rather | ||
| # than failing the whole request. | ||
| logger.info( | ||
| "filter_and_transform_events_for_client: no state for always-included" | ||
| " outlier %s; returning it without a membership annotation", | ||
| event.event_id, | ||
| ) | ||
| return FilteredEvent(event=filtered, membership=None) | ||
|
|
||
| user_membership = ( | ||
| user_membership_event.membership | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is listed as fixing #19858 which tracks a flake I specifically saw with
TestFederationRoomsInvite/Parallel/Remote_invited_user_can_reject_invite_when_homeserver_is_already_participating_in_the_roomFrom a message you sent in the internal backend room, it looks like you saw this flake with
TestFederationRoomsInvite/Parallel/Invited_user_can_reject_invite_over_federation_several_times(different test)It makes sense that this would probably fix up both as they both involve out-of-band membership (invites over federation)