_fixes_re in src/sentry/utils/groupreference.py:
_fixes_re = re.compile(
rf"\b{_fix_keywords}:?\s+([A-Za-z0-9_\-\s\,]+)\b",
re.I,
)
The \s inside the ID-list character class also matches newlines, so the match swallows every line after the keyword, and _short_id_re then pulls short-ID-shaped tokens out of narrative prose. For example:
Fixes SENTRY-1
Backported from OTHER-456 for the release branch
The IDs treated as fixed come out as ['SENTRY-1', 'OTHER-456'], when only SENTRY-1 was meant.
This matters because Commit.find_referenced_groups() and PullRequest.find_referenced_groups() feed the resolved_in_commit / resolved_in_pull_request receivers, which create GroupLink(relationship=resolves) records. A phantom ID that happens to resolve to a real group in the org can then get auto-resolved by a release containing that commit. The \s was clearly intended for same-line separators like Fixes A-1, B-2, not newlines.
(find_fix_statements, used by the Seer RPC path, works per-line and is not affected.)
Observed on master at bb47162e (2026-09-25).
_fixes_reinsrc/sentry/utils/groupreference.py:The
\sinside the ID-list character class also matches newlines, so the match swallows every line after the keyword, and_short_id_rethen pulls short-ID-shaped tokens out of narrative prose. For example:The IDs treated as fixed come out as
['SENTRY-1', 'OTHER-456'], when onlySENTRY-1was meant.This matters because
Commit.find_referenced_groups()andPullRequest.find_referenced_groups()feed theresolved_in_commit/resolved_in_pull_requestreceivers, which createGroupLink(relationship=resolves)records. A phantom ID that happens to resolve to a real group in the org can then get auto-resolved by a release containing that commit. The\swas clearly intended for same-line separators likeFixes A-1, B-2, not newlines.(
find_fix_statements, used by the Seer RPC path, works per-line and is not affected.)Observed on master at
bb47162e(2026-09-25).