Skip to content

fix(deletions): Avoid DoesNotExist crash when FK target is already deleted#112375

Merged
swartzrock merged 1 commit intomasterfrom
swartzrock/workflow-deletion-bug
Apr 7, 2026
Merged

fix(deletions): Avoid DoesNotExist crash when FK target is already deleted#112375
swartzrock merged 1 commit intomasterfrom
swartzrock/workflow-deletion-bug

Conversation

@swartzrock
Copy link
Copy Markdown
Member

DetectorDeletionTask and WorkflowDeletionTask both accessed FK descriptors (instance.workflow_condition_group, instance.when_condition_group) to check whether to include a related DataConditionGroup in child relations. When the referenced row has already been deleted, Django raises DoesNotExist.

Because _run_deletion swallows all exceptions in production without re-raising, this caused the deletion task to silently fail and enter an infinite retry loop via reattempt_deletions. Orgs with detectors or workflows in this state can stay stuck in DELETION_IN_PROGRESS indefinitely.

Fix by reading the raw FK id field instead of going through the descriptor, which avoids the database lookup and the potential DoesNotExist entirely.

Fixes SENTRY-5M8C

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Apr 7, 2026
@swartzrock swartzrock force-pushed the swartzrock/workflow-deletion-bug branch from cef1e78 to 68e8db2 Compare April 7, 2026 16:46
# Verify the error path in DetectorDeletionTask was actually exercised.
mock_remove_seat_subscriptions.assert_called_once()

def test_dangling_workflow_condition_group(self) -> None:
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.

is there a test that reproduces the exact bug? like the repeating queuing and failure to delete

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

how does test_dangling_fk_causes_stuck_deletion_loop() look?

@swartzrock swartzrock force-pushed the swartzrock/workflow-deletion-bug branch 2 times, most recently from 3756a03 to 4ec6d3b Compare April 7, 2026 17:25
…leted

DetectorDeletionTask and WorkflowDeletionTask both accessed FK descriptors
(instance.workflow_condition_group, instance.when_condition_group) to check
whether to include a related DataConditionGroup in child relations. When the
referenced row has already been deleted, Django raises DoesNotExist.

Because _run_deletion swallows all exceptions in production without re-raising,
this caused the deletion task to silently fail and enter an infinite retry loop
via reattempt_deletions. Orgs with detectors or workflows in this state can
stay stuck in DELETION_IN_PROGRESS indefinitely.

Fix by reading the raw FK id field instead of going through the descriptor,
which avoids the database lookup and the potential DoesNotExist entirely.

Fixes SENTRY-5M8C
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@swartzrock swartzrock force-pushed the swartzrock/workflow-deletion-bug branch from 4ec6d3b to e2eee00 Compare April 7, 2026 18:44
@swartzrock swartzrock marked this pull request as ready for review April 7, 2026 18:44
@swartzrock swartzrock requested review from a team as code owners April 7, 2026 18:44
@swartzrock swartzrock requested a review from markstory April 7, 2026 18:45
Copy link
Copy Markdown
Contributor

@saponifi3d saponifi3d left a comment

Choose a reason for hiding this comment

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

lgtm - thanks for making this fix! 🙏

@swartzrock swartzrock merged commit 108ee22 into master Apr 7, 2026
60 checks passed
@swartzrock swartzrock deleted the swartzrock/workflow-deletion-bug branch April 7, 2026 19:15
george-sentry pushed a commit that referenced this pull request Apr 9, 2026
…leted (#112375)

DetectorDeletionTask and WorkflowDeletionTask both accessed FK
descriptors (instance.workflow_condition_group,
instance.when_condition_group) to check whether to include a related
DataConditionGroup in child relations. When the referenced row has
already been deleted, Django raises DoesNotExist.

Because _run_deletion swallows all exceptions in production without
re-raising, this caused the deletion task to silently fail and enter an
infinite retry loop via reattempt_deletions. Orgs with detectors or
workflows in this state can stay stuck in DELETION_IN_PROGRESS
indefinitely.

Fix by reading the raw FK id field instead of going through the
descriptor, which avoids the database lookup and the potential
DoesNotExist entirely.

Fixes [SENTRY-5M8C](https://sentry.sentry.io/issues/7344636431)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants