-
Bug
-
Resolution: Done
-
Normal
-
None
-
Quality / Stability / Reliability
-
False
-
-
None
-
Important
-
None
-
None
-
None
-
None
-
None
-
None
Summary
Alerts with the same alertname but different labels (namespace, severity, component) incorrectly show the same silence state in the Incidents UI. When one alert is silenced, all alerts with the same name appear silenced, regardless of whether the silence matchers match their specific labels.
Description
Problem Statement
The Incidents page incorrectly applies silence state to alerts by matching only on alertname, ignoring other critical label fields such as namespace, severity, and component. This causes alerts that should not be silenced to display as silenced in the UI when another alert with the same name is silenced.
Root Cause
In processAlerts.ts, the code matches alerts to Prometheus rules using only the alert name:
// Line 167 in processAlerts()const matchingRule = alertingRules.find((rule) => rule.name === alert.metric.alertname);// Line 186
silenced: matchingRule ? matchingRule.state === 'silenced' : false,
And similarly in groupAlertsForTable():
{{// Lines 200-203
if (alertingRulesData): { rule = alertingRulesData.find((rule) => alertname === rule.name); }const silenced = rule?.state === 'silenced';}}
This naive lookup returns the first rule with a matching name, regardless of whether that rule's alert instances match the specific alert's labels. When multiple alerts share the same name but differ in other labels, they all get assigned the same rule and thus the same silence state.
I tested it with following silences rules:

And alerts:

And both of the alerts are shown as silences, only though the rule should match only the storage one.

Silence matching in other components
web/src/components/alerting/AlertUtils.tsx:
// Lines 555-566
const isAlertSilenced = (alert: PrometheusAlert, silence: Silence): boolean => {
return (
isAlertFiring(alert) &&
silence.matchers.every((matcher) => {
const alertValue = alert.labels[matcher.name] ?? '';
const isMatch = matcher.isRegex
? new RegExp(`^${matcher.value}$`).test(alertValue)
: alertValue === matcher.value;
return matcher.isEqual === false && alertValue ? !isMatch : isMatch;
})
);
};
As oposed to the code in Incidents/processAlerts.ts, it matches all the labels that the silence carries.