Skip to content

Conversation

@evanpurkhiser
Copy link
Member

@evanpurkhiser evanpurkhiser commented Nov 25, 2025

Previously, detectors were created as part of the endpoint, after detector → alerts linking happened. This changes it so detectors are crated immediately after the cron monitor is created.

Changes:

  • Moved ensure_cron_detector() call from endpoint into MonitorValidator.create()
  • Detector is created BEFORE alert_rule creation, allowing IssueAlertMigrator
    to find and link it to workflows
  • Added skip_detector_creation context flag to prevent duplicate creation
    when using MonitorDataSourceValidator (new detector flow)
  • Updated tests to verify detector creation

This ensures both the old (MonitorValidator) and new (detector API) flows
correctly create detectors for all monitors.

Part of NEW-593: Cron Monitor Alerts are not linked to monitor when created via the old flow

@evanpurkhiser evanpurkhiser requested a review from a team as a code owner November 25, 2025 20:06
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Nov 25, 2025
@evanpurkhiser evanpurkhiser force-pushed the evanpurkhiser/feat-crons-always-create-detectors-for-all-monitors-in-monitorvalidator branch from 176840f to e7183ca Compare November 25, 2025 20:32
…ator

Previously, detectors were only created conditionally (when alert_rule
was present), but every cron monitor should have a detector. The original
endpoint code from commit 450bde5 always called ensure_cron_detector()
for all monitors.

Changes:
- Moved ensure_cron_detector() call from endpoint into MonitorValidator.create()
- Detector creation now happens for ALL monitors (not just those with alert_rule)
- Detector is created BEFORE alert_rule creation, allowing IssueAlertMigrator
  to find and link it to workflows
- Added skip_detector_creation context flag to prevent duplicate creation
  when using MonitorDataSourceValidator (new detector flow)
- Updated tests to verify detector creation

This ensures both the old (MonitorValidator) and new (detector API) flows
correctly create detectors for all monitors.
@evanpurkhiser evanpurkhiser force-pushed the evanpurkhiser/feat-crons-always-create-detectors-for-all-monitors-in-monitorvalidator branch from e7183ca to cc04746 Compare November 26, 2025 17:33
from_detector_flow = self.context.get("from_detector_flow", False)

if not from_detector_flow:
detector = ensure_cron_detector(monitor)
Copy link

Choose a reason for hiding this comment

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

Bug: ensure_cron_detector() can return None, leading to an AssertionError at assert detector during monitor creation.
Severity: CRITICAL | Confidence: High

🔍 Detailed Analysis

The ensure_cron_detector() function can return None if Detector.objects.get() fails (e.g., DoesNotExist) when trying to retrieve an existing detector. This can occur if a DataSource exists without a linked Detector, or due to a mismatch in detector creation logic. When ensure_cron_detector() returns None, the subsequent assert detector at src/sentry/monitors/validators.py:382 will raise an AssertionError, causing an unhandled HTTP 500 error in the monitor creation endpoint and potentially leaving orphaned monitors.

💡 Suggested Fix

Replace assert detector with an explicit if detector is None: check. Handle the None case gracefully by raising a specific validation error or returning an appropriate error response, rather than crashing the server with an AssertionError.

🤖 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/monitors/validators.py#L382

Potential issue: The `ensure_cron_detector()` function can return `None` if
`Detector.objects.get()` fails (e.g., `DoesNotExist`) when trying to retrieve an
existing detector. This can occur if a `DataSource` exists without a linked `Detector`,
or due to a mismatch in detector creation logic. When `ensure_cron_detector()` returns
`None`, the subsequent `assert detector` at `src/sentry/monitors/validators.py:382` will
raise an `AssertionError`, causing an unhandled HTTP 500 error in the monitor creation
endpoint and potentially leaving orphaned monitors.

Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 3856920


if not from_detector_flow:
detector = ensure_cron_detector(monitor)
assert detector
Copy link
Contributor

Choose a reason for hiding this comment

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

Bug: Assert statement in production code causes crash

The assert detector statement will crash with an AssertionError when ensure_cron_detector returns None (which happens when database errors occur or a detector is missing). Assert statements should not be used for error handling in production code. This prevents graceful error handling and will cause monitor creation to fail unexpectedly.

Fix in Cursor Fix in Web

Copy link
Member Author

Choose a reason for hiding this comment

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

That's fine this should probably be a hard fail

except Exception:
logger.exception("Error creating cron detector")

return None
Copy link
Member

Choose a reason for hiding this comment

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

Do you need to return None? Isn't it always bad if you don't create or find the appropriate detector

Copy link
Member Author

Choose a reason for hiding this comment

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

Right I could probably change this to be an exception. I’ll clean that up

@codecov
Copy link

codecov bot commented Nov 26, 2025

Codecov Report

❌ Patch coverage is 70.00000% with 3 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/sentry/monitors/utils.py 60.00% 2 Missing ⚠️
src/sentry/monitors/validators.py 80.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           master   #104004      +/-   ##
===========================================
- Coverage   80.62%    80.60%   -0.02%     
===========================================
  Files        9317      9317              
  Lines      397599    397702     +103     
  Branches    25393     25393              
===========================================
+ Hits       320549    320568      +19     
- Misses      76598     76682      +84     
  Partials      452       452              

@evanpurkhiser evanpurkhiser merged commit a93dfcf into master Nov 26, 2025
67 checks passed
@evanpurkhiser evanpurkhiser deleted the evanpurkhiser/feat-crons-always-create-detectors-for-all-monitors-in-monitorvalidator branch November 26, 2025 18:20
@linear
Copy link

linear bot commented Nov 26, 2025

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.

3 participants