fix(workflows): Handle duplicated AlertRuleWorkflow entries for a Workflow more gracefully#113138
fix(workflows): Handle duplicated AlertRuleWorkflow entries for a Workflow more gracefully#113138
Conversation
…kflow more gracefully
| rule_id = alert_rule_workflow.rule_id | ||
| except AlertRuleWorkflow.DoesNotExist: | ||
| rule_id = None |
There was a problem hiding this comment.
Bug: The call to AlertRuleWorkflow.objects.get() does not handle the MultipleObjectsReturned exception, which can occur if duplicate entries exist for a project, leading to a crash.
Severity: HIGH
Suggested Fix
Modify the except block to catch both AlertRuleWorkflow.DoesNotExist and AlertRuleWorkflow.MultipleObjectsReturned exceptions. This pattern is common elsewhere in the codebase for handling .get() calls.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: src/sentry/rules/history/backends/postgres.py#L67-L69
Potential issue: The `get_rule_workflow` function calls
`AlertRuleWorkflow.objects.get()` to retrieve a workflow. While the query is filtered by
`project_id`, it is still possible for multiple `AlertRuleWorkflow` entries to exist for
different rules within the same project. The code only handles the `DoesNotExist`
exception. If the query returns multiple objects, it will raise an unhandled
`MultipleObjectsReturned` exception, causing a crash in the
`ProjectRuleStatsIndexEndpoint` and `ProjectRuleGroupHistoryIndexEndpoint` API handlers.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 926e629. Configure here.
| # scope to the project. Django evaluates this as a single SQL | ||
| # statement (subquery), not a separate round-trip. | ||
| qs = qs.filter(rule_id__in=Rule.objects.filter(project_id=project_id).values("id")) | ||
| alert_rule_workflow = qs.get() |
There was a problem hiding this comment.
MultipleObjectsReturned not caught despite graceful-handling intent
Medium Severity
The qs.get() call can still raise MultipleObjectsReturned if more than one AlertRuleWorkflow matches after filtering — for example, if two distinct rules in the same project both point to the same workflow. The try/except only catches AlertRuleWorkflow.DoesNotExist, so a MultipleObjectsReturned exception would propagate as an unhandled 500 error. Since the PR's stated goal is to "avoid crashing," catching (or otherwise handling) MultipleObjectsReturned — e.g., by using qs.first() or adding it to the except clause — would make the fix more robust.
Reviewed by Cursor Bugbot for commit 926e629. Configure here.
There was a problem hiding this comment.
it's true, but shouldn't convention avoid this and we'd want to be notified about this as a different error?
|
The bots are right, this doesn't fully prevent, but we're only trying to avoid the known duplication issue with one item per project. |


We've got a few fixes for this situation in the works, but if we can avoid crashing in the meantime that seems ideal.
Part of ISWF-2470.