From 6204cf65eea216923b2002ee2f9241e1c9b6f624 Mon Sep 17 00:00:00 2001 From: Greg Pstrucha <875316+gricha@users.noreply.github.com> Date: Tue, 3 Nov 2026 12:44:01 -0800 Subject: [PATCH] fix(teams): Keep a team's issue subscriptions when removing a pending invite Removing a member from a team unsubscribes them from the team's issues with GroupSubscription.filter(user_id=member.user_id). A pending invite has no user, so user_id=None matched the team's own subscriptions (user_id is NULL on those rows) and deleted them. --- .../organization_member_team_details.py | 3 +++ .../test_organization_member_team_details.py | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/sentry/core/endpoints/organization_member_team_details.py b/src/sentry/core/endpoints/organization_member_team_details.py index 1636bb78ffd4..12c16999010c 100644 --- a/src/sentry/core/endpoints/organization_member_team_details.py +++ b/src/sentry/core/endpoints/organization_member_team_details.py @@ -586,6 +586,9 @@ def _unsubscribe_issues(team: Team, member: OrganizationMember) -> None: """ Unsubscribe user from issues the team is subscribed to """ + # A pending invite has no subscriptions, and user_id=None would match the team's own. + if member.user_id is None: + return team_assigned_groups = GroupAssignee.objects.filter(team_id=team.id).values_list( "group_id", flat=True ) diff --git a/tests/sentry/core/endpoints/test_organization_member_team_details.py b/tests/sentry/core/endpoints/test_organization_member_team_details.py index 0aed8bcef1f5..51b8d328758a 100644 --- a/tests/sentry/core/endpoints/test_organization_member_team_details.py +++ b/tests/sentry/core/endpoints/test_organization_member_team_details.py @@ -801,6 +801,26 @@ def test_cannot_leave_idp_provisioned_team(self) -> None: team=idp_team, organizationmember=member ).exists() + def test_removing_pending_invite_keeps_team_subscriptions(self) -> None: + invite = self.create_member( + organization=self.org, email="invited@example.com", role="member", teams=[self.team] + ) + group = self.create_group() + GroupAssignee.objects.create(group=group, team=self.team, project=group.project) + GroupSubscription.objects.create( + group=group, + project=group.project, + team=self.team, + reason=GroupSubscriptionReason.assigned, + ) + + self.login_as(self.user) + self.get_success_response( + self.org.slug, invite.id, self.team.slug, status_code=status.HTTP_200_OK + ) + + assert GroupSubscription.objects.filter(group=group, team=self.team).exists() + def test_unsubscribe_user_from_team_issues_legacy(self) -> None: """ We have some legacy DB rows from before the GroupSubscription table had a team_id