Problem
When a crash-free rate metric alert is represented as a metric issue (new detector-backed issue type), the "Correlated Issues" section does not appear — or appears but fails silently. This is a regression from the old metric alert detail page, which reliably showed a "Related Issues" section filtered by error.unhandled:true.
Background: old behavior
On the old metric alert detail page (/alerts/metric-rules/{ruleId}/), the alert rule object is loaded directly from the URL's rule ID. For crash-free rate alerts (Dataset.SESSIONS or Dataset.METRICS), body.tsx always renders:
// static/app/views/alerts/rules/metric/details/body.tsx
{[Dataset.METRICS, Dataset.SESSIONS, Dataset.ERRORS].includes(dataset) && (
<RelatedIssues
rule={rule}
query={isCrashFreeAlert(dataset) ? `${query} error.unhandled:true`.trim() : undefined}
timePeriod={timePeriod}
...
/>
)}
Because the rule is loaded by alert rule ID from the URL, this section always worked.
New behavior: two failure modes in MetricIssuesSection
Failure mode 1 — section never renders
In groupEventDetailsContent.tsx, MetricIssuesSection only mounts when:
{(event.contexts?.metric_alert?.alert_rule_id ||
event?.occurrence?.evidenceData?.alertId) && (
<MetricIssuesSection ... />
)}
For detector-backed metric issues (occurrence type 8001), these legacy fields may not be populated. getDetectorDetails() in detectorSection.tsx correctly identifies such issues as detectorType: 'metric_alert' — but that check is not used in the render condition. Session-based (crash-free rate) metric issues are especially likely to be missing those legacy fields because there is no underlying error event to carry them.
Failure mode 2 — section renders but silently fails to load the rule
Even when the section does render, MetricIssuesSection resolves the metric alert rule like this:
// static/app/views/issueDetails/metricIssues/metricIssuesSection.tsx
const ruleId = useMetricIssueAlertId({groupId: group.id});
const {data: rule} = useMetricRule({orgSlug, ruleId});
useMetricIssueAlertId (metricIssues/utils.tsx) does:
const hasMetricDetector = detectorId && detectorType === 'metric_alert';
// detectorId comes from event.occurrence?.evidenceData.detectorId — the workflow engine detector ID
return hasMetricDetector ? detectorId : fallback;
useMetricRule then hits:
GET /organizations/{org}/alert-rules/{alertRuleId}/
The problem: the code passes the workflow-engine detector ID to an endpoint that expects an alert rule ID. These are different entities with different numeric IDs. detectorSection.tsx already acknowledges this mapping problem — its MetricAlertSection fetches the detector object and reads metricDetector.alertRuleId to get the actual alert rule ID. No equivalent translation exists in MetricIssuesSection.
When useMetricRule receives the wrong ID it returns nothing, MetricIssuesSection returns null, and the correlated issues panel is invisible for crash-free metric issues.
Why crash-free rate is most affected
- Crash-free rate alerts use
Dataset.SESSIONS — they fire on session-derived percentages, not on individual error events.
- When a crash-free metric issue is created, its occurrence likely lacks the legacy
alert_rule_id / alertId fields (no error event to attach them to), so failure mode 1 is more likely to trigger.
- Even if the section does render, the detector ID → alert rule ID mismatch (failure mode 2) silently breaks rule loading.
Proposed fixes
1. Fix the render condition (failure mode 1)
Also gate on detector metadata so detector-backed metric issues are not excluded:
// groupEventDetailsContent.tsx
const isMetricIssue =
event.occurrence?.type === 8001 ||
detectorDetails.detectorType === 'metric_alert' ||
!!event.contexts?.metric_alert?.alert_rule_id ||
!!event?.occurrence?.evidenceData?.alertId;
{isMetricIssue && <MetricIssuesSection ... />}
2. Fix alert rule ID resolution (failure mode 2)
useMetricIssueAlertId should resolve the alert rule ID — not the detector ID:
// Current — wrong when hasMetricDetector is true:
return hasMetricDetector ? detectorId : fallback;
// Better — prefer alert rule ID fields, fall back to a detector→rule lookup:
return (
event?.occurrence?.evidenceData?.alertId ??
event?.contexts?.metric_alert?.alert_rule_id ??
metricDetector?.alertRuleId // via /alert-rule-detector/ like MetricAlertSection
);
Alternatively, MetricIssuesSection could use the /organizations/{org}/alert-rule-detector/?alert_rule_id=... endpoint (already used by MetricAlertOngoingIssues) to translate detector ID → alert rule ID before calling useMetricRule.
3. Backend hardening (optional)
Ensure crash-free rate metric issue occurrences (type 8001) always populate evidenceData.alertId with the linked alert rule ID, making the frontend fallback path reliable without a secondary lookup.
Files involved
| File |
Role |
static/app/views/issueDetails/groupEventDetails/groupEventDetailsContent.tsx |
Controls whether MetricIssuesSection renders |
static/app/views/issueDetails/metricIssues/metricIssuesSection.tsx |
Correlated issues section for metric issues |
static/app/views/issueDetails/metricIssues/utils.tsx — useMetricIssueAlertId |
Resolves rule ID (currently returns detector ID instead) |
static/app/views/alerts/rules/metric/utils/useMetricRule.tsx |
Fetches alert rule by ID |
static/app/views/alerts/rules/metric/details/relatedIssues.tsx |
Shared RelatedIssues component |
static/app/views/issueDetails/streamline/sidebar/detectorSection.tsx |
getDetectorDetails sets detectorType: 'metric_alert' correctly but it is unused in the render gate |
Secondary observation
isCrashFreeAlert(dataset) returns true for both Dataset.SESSIONS and Dataset.METRICS. If any non-crash-free alert uses Dataset.METRICS, those alerts would incorrectly have error.unhandled:true appended to their correlated-issues query. Worth auditing separately once the primary bug is fixed.
View Session in Sentry
Problem
When a crash-free rate metric alert is represented as a metric issue (new detector-backed issue type), the "Correlated Issues" section does not appear — or appears but fails silently. This is a regression from the old metric alert detail page, which reliably showed a "Related Issues" section filtered by
error.unhandled:true.Background: old behavior
On the old metric alert detail page (
/alerts/metric-rules/{ruleId}/), the alert rule object is loaded directly from the URL's rule ID. For crash-free rate alerts (Dataset.SESSIONSorDataset.METRICS),body.tsxalways renders:Because the rule is loaded by alert rule ID from the URL, this section always worked.
New behavior: two failure modes in
MetricIssuesSectionFailure mode 1 — section never renders
In
groupEventDetailsContent.tsx,MetricIssuesSectiononly mounts when:For detector-backed metric issues (occurrence type
8001), these legacy fields may not be populated.getDetectorDetails()indetectorSection.tsxcorrectly identifies such issues asdetectorType: 'metric_alert'— but that check is not used in the render condition. Session-based (crash-free rate) metric issues are especially likely to be missing those legacy fields because there is no underlying error event to carry them.Failure mode 2 — section renders but silently fails to load the rule
Even when the section does render,
MetricIssuesSectionresolves the metric alert rule like this:useMetricIssueAlertId(metricIssues/utils.tsx) does:useMetricRulethen hits:The problem: the code passes the workflow-engine detector ID to an endpoint that expects an alert rule ID. These are different entities with different numeric IDs.
detectorSection.tsxalready acknowledges this mapping problem — itsMetricAlertSectionfetches the detector object and readsmetricDetector.alertRuleIdto get the actual alert rule ID. No equivalent translation exists inMetricIssuesSection.When
useMetricRulereceives the wrong ID it returns nothing,MetricIssuesSectionreturnsnull, and the correlated issues panel is invisible for crash-free metric issues.Why crash-free rate is most affected
Dataset.SESSIONS— they fire on session-derived percentages, not on individual error events.alert_rule_id/alertIdfields (no error event to attach them to), so failure mode 1 is more likely to trigger.Proposed fixes
1. Fix the render condition (failure mode 1)
Also gate on detector metadata so detector-backed metric issues are not excluded:
2. Fix alert rule ID resolution (failure mode 2)
useMetricIssueAlertIdshould resolve the alert rule ID — not the detector ID:Alternatively,
MetricIssuesSectioncould use the/organizations/{org}/alert-rule-detector/?alert_rule_id=...endpoint (already used byMetricAlertOngoingIssues) to translate detector ID → alert rule ID before callinguseMetricRule.3. Backend hardening (optional)
Ensure crash-free rate metric issue occurrences (type
8001) always populateevidenceData.alertIdwith the linked alert rule ID, making the frontend fallback path reliable without a secondary lookup.Files involved
static/app/views/issueDetails/groupEventDetails/groupEventDetailsContent.tsxMetricIssuesSectionrendersstatic/app/views/issueDetails/metricIssues/metricIssuesSection.tsxstatic/app/views/issueDetails/metricIssues/utils.tsx—useMetricIssueAlertIdstatic/app/views/alerts/rules/metric/utils/useMetricRule.tsxstatic/app/views/alerts/rules/metric/details/relatedIssues.tsxRelatedIssuescomponentstatic/app/views/issueDetails/streamline/sidebar/detectorSection.tsxgetDetectorDetailssetsdetectorType: 'metric_alert'correctly but it is unused in the render gateSecondary observation
isCrashFreeAlert(dataset)returnstruefor bothDataset.SESSIONSandDataset.METRICS. If any non-crash-free alert usesDataset.METRICS, those alerts would incorrectly haveerror.unhandled:trueappended to their correlated-issues query. Worth auditing separately once the primary bug is fixed.View Session in Sentry