diff --git a/federationsender/internal/perform.go b/federationsender/internal/perform.go index 90abae236..30950f528 100644 --- a/federationsender/internal/perform.go +++ b/federationsender/internal/perform.go @@ -108,6 +108,7 @@ func (r *FederationSenderInternalAPI) PerformJoin( ) } +// nolint:gocyclo func (r *FederationSenderInternalAPI) performJoinUsingServer( ctx context.Context, roomID, userID string, @@ -192,6 +193,19 @@ func (r *FederationSenderInternalAPI) performJoinUsingServer( return fmt.Errorf("joinCtx.CheckSendJoinResponse: %w", err) } + // It's possible that the remote server has included our new + // membership event in the room state in the send_join response, + // but if that's the case, then we'll get a duplicate state block + // error if we try to send that along with our own copy of the + // event. The simple way around this is just to prune the event + // from the state if we find it. + for i, ev := range respState.StateEvents { + if ev.Type() == gomatrixserverlib.MRoomMember && ev.StateKeyEquals(userID) { + respState.StateEvents = append(respState.StateEvents[i:], respState.StateEvents[:i+1]...) + break + } + } + // If we successfully performed a send_join above then the other // server now thinks we're a part of the room. Send the newly // returned state to the roomserver to update our local view.