Skip to content

fix(msteams): Prevent AssertionError when rule lacks legacy_rule_id - #120644

Draft
sentry[bot] wants to merge 1 commit into
masterfrom
seer/fix/msteams-rule-id-assertion
Draft

fix(msteams): Prevent AssertionError when rule lacks legacy_rule_id#120644
sentry[bot] wants to merge 1 commit into
masterfrom
seer/fix/msteams-rule-id-assertion

Conversation

@sentry

@sentry sentry Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

This PR fixes an AssertionError occurring in the MS Teams webhook handler (/extensions/msteams/webhook/).

The root cause was that build_rule_url in src/sentry/integrations/messaging/message_builder.py unconditionally called get_key_from_rule_data(rule, "legacy_rule_id"). The get_key_from_rule_data function contains an assertion that value is not None, which would fail if the rule.data.actions[0] dictionary did not contain the legacy_rule_id key. This happened for certain older rules or rules without this specific field set.

The build_footer function, which calls build_rule_url, already correctly determines the rule ID using get_rule_or_workflow_id, which includes fallback logic (e.g., to str(rule.id)).

The fix modifies build_rule_url to accept the already-resolved rule_id as a parameter. build_footer now passes this safely resolved rule_id to build_rule_url, thus bypassing the problematic assertion and preventing the AssertionError.

Legal Boilerplate

Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.

Fixes SENTRY-4EPX

Comment @sentry <feedback> on this PR to have Autofix iterate on the changes.

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Jul 27, 2026
Comment on lines +250 to +253
def build_rule_url(rule: Any, group: Group, project: Project, rule_id: str | None = None) -> str:
org_slug = group.organization.slug
project_slug = project.slug
rule_id = get_key_from_rule_data(rule, "legacy_rule_id")
if rule_id is None:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

build_rule_url fallback still exposes AssertionError for Slack and notification callers

The build_rule_url fallback to get_key_from_rule_data preserves the same AssertionError in Slack build_slack_footer and notification get_notification_title paths, which still call the function without passing the safely resolved rule_id.

Evidence
  • build_slack_footer in slack/message_builder/util.py calls get_rule_or_workflow_id(rules[0]) safely, then calls build_rule_url(rules[0], group, project) without the resolved value.
  • get_notification_title in notifications/notifications/rules.py follows the same pattern, calling build_rule_url without the resolved value.
  • When get_rule_or_workflow_id falls back to str(rule.id), it still returns the "legacy_rule_id" key, causing both callers to enter that match branch.
  • build_rule_url then calls get_key_from_rule_data(rule, "legacy_rule_id"), which asserts value is not None and raises AssertionError when the rule data lacks that key.

Identified by Warden · sentry-backend-bugs · 4WC-TWT

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.

0 participants