diff --git a/src/sentry/workflow_engine/processors/detector.py b/src/sentry/workflow_engine/processors/detector.py index c99f5a7555ed56..9baaf8f29cd9e9 100644 --- a/src/sentry/workflow_engine/processors/detector.py +++ b/src/sentry/workflow_engine/processors/detector.py @@ -382,6 +382,28 @@ def associate_new_group_with_detector(group: Group, detector_id: int | None = No }, ) return False + + # Check if the detector exists. If not, create DetectorGroup with null detector_id + # to make it clear that we were associated with a detector that no longer exists. + if not Detector.objects.filter(id=detector_id).exists(): + metrics.incr( + "workflow_engine.associate_new_group_with_detector", + tags={"group_type": group.type, "result": "detector_missing"}, + ) + logger.warning( + "associate_new_group_with_detector_detector_missing", + extra={ + "group_id": group.id, + "group_type": group.type, + "detector_id": detector_id, + }, + ) + DetectorGroup.objects.get_or_create( + detector_id=None, + group_id=group.id, + ) + return True + DetectorGroup.objects.get_or_create( detector_id=detector_id, group_id=group.id, diff --git a/tests/sentry/workflow_engine/processors/test_detector.py b/tests/sentry/workflow_engine/processors/test_detector.py index 7509117ecd7389..c46ac599dbd3ba 100644 --- a/tests/sentry/workflow_engine/processors/test_detector.py +++ b/tests/sentry/workflow_engine/processors/test_detector.py @@ -1058,3 +1058,15 @@ def test_feedback_group_returns_false(self) -> None: group = self.create_group(project=self.project, type=FeedbackGroup.type_id) assert not associate_new_group_with_detector(group) assert not DetectorGroup.objects.filter(group_id=group.id).exists() + + def test_deleted_detector_creates_null_association(self) -> None: + group = self.create_group(project=self.project, type=MetricIssue.type_id) + deleted_detector_id = self.metric_detector.id + + self.metric_detector.delete() + + assert associate_new_group_with_detector(group, deleted_detector_id) + + detector_group = DetectorGroup.objects.get(group_id=group.id) + assert detector_group.detector_id is None + assert detector_group.group_id == group.id