Skip to content

Conversation

@beezz
Copy link
Contributor

@beezz beezz commented Nov 11, 2025

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.

This uniq index and was added in #27064
for CDC and is no longer needed.
@beezz beezz requested review from a team as code owners November 11, 2025 11:16
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Nov 11, 2025
Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Uniqueness Constraint: Foundation of Counter System

Removing the unique_together constraint on (project, short_id) breaks the stuck counter detection and fixing logic in event_manager.py. The _is_stuck_counter_error function relies on detecting UniqueViolation errors on this constraint to automatically fix stuck project counters. Without this constraint, duplicate short_id values within a project can exist undetected, breaking the qualified short ID system which assumes uniqueness.

src/sentry/models/group.py#L693-L694

models.Index(fields=("project", "status", "priority", "last_seen", "id")),
]

Fix in Cursor Fix in Web


Comment on lines +22 to +32

dependencies = [
("sentry", "1003_group_history_prev_history_safe_removal"),
]

operations = [
migrations.AlterUniqueTogether(
name="group",
unique_together=set(),
),
]
Copy link

Choose a reason for hiding this comment

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

Bug: Removing the (project, short_id) unique constraint disables critical "stuck counter" error detection, leading to silent duplicate group creation.
Severity: CRITICAL | Confidence: 0.95

🔍 Detailed Analysis

The removal of the unique constraint (project, short_id) from the Group model will disable the existing error handling mechanism for "stuck counter" conditions. Specifically, the _is_stuck_counter_error function, which relies on catching psycopg2.errors.UniqueViolation for the sentry_groupedmessage_project_id_short_id constraint, will no longer trigger. This means that if the Counter mechanism for generating short_id values gets out of sync with existing group short_ids (a condition that has occurred in production, as evidenced by the comment "< 20 ever that we know of" in _handle_stuck_project_counter), duplicate groups with identical (project_id, short_id) values will be silently created instead of being detected and recovered.

💡 Suggested Fix

Either re-evaluate the necessity of removing the (project, short_id) unique constraint, or update the _is_stuck_counter_error and _handle_stuck_project_counter functions to use an alternative, robust mechanism for detecting and recovering from short_id synchronization issues without relying on a database unique constraint.

🤖 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/migrations/1004_remove_group_project_short_id_unique_constraint.py#L1-L32

Potential issue: The removal of the unique constraint `(project, short_id)` from the
`Group` model will disable the existing error handling mechanism for "stuck counter"
conditions. Specifically, the `_is_stuck_counter_error` function, which relies on
catching `psycopg2.errors.UniqueViolation` for the
`sentry_groupedmessage_project_id_short_id` constraint, will no longer trigger. This
means that if the `Counter` mechanism for generating `short_id` values gets out of sync
with existing group `short_id`s (a condition that has occurred in production, as
evidenced by the comment "< 20 ever that we know of" in
`_handle_stuck_project_counter`), duplicate groups with identical `(project_id,
short_id)` values will be silently created instead of being detected and recovered.

Did we get this right? 👍 / 👎 to inform future reviews.

@github-actions
Copy link
Contributor

This PR has a migration; here is the generated SQL for src/sentry/migrations/1004_remove_group_project_short_id_unique_constraint.py

for 1004_remove_group_project_short_id_unique_constraint in sentry

--
-- Alter unique_together for group (0 constraint(s))
--
ALTER TABLE "sentry_groupedmessage" DROP CONSTRAINT "sentry_groupedmessage_project_id_short_id_29374dd7_uniq";

@beezz beezz marked this pull request as draft November 11, 2025 11:26
@codecov
Copy link

codecov bot commented Nov 11, 2025

❌ 3 Tests Failed:

Tests completed Failed Passed Skipped
29575 3 29572 243
View the top 3 failed test(s) by shortest run time
tests.sentry.models.test_projectcounter::test_group_creation_with_stuck_project_counter[ discrepancy = 3 ]
Stack Traces | 5.29s run time
#x1B[1m#x1B[.../sentry/models/test_projectcounter.py#x1B[0m:119: in test_group_creation_with_stuck_project_counter
    assert group_creation_spy.call_count == 2
#x1B[1m#x1B[31mE   AssertionError: assert 1 == 2#x1B[0m
#x1B[1m#x1B[31mE    +  where 1 = <MagicMock id='140689969819200'>.call_count#x1B[0m
tests.sentry.models.test_projectcounter::test_group_creation_with_stuck_project_counter[ discrepancy = 1 ]
Stack Traces | 5.82s run time
#x1B[1m#x1B[.../sentry/models/test_projectcounter.py#x1B[0m:119: in test_group_creation_with_stuck_project_counter
    assert group_creation_spy.call_count == 2
#x1B[1m#x1B[31mE   AssertionError: assert 1 == 2#x1B[0m
#x1B[1m#x1B[31mE    +  where 1 = <MagicMock id='139760723896576'>.call_count#x1B[0m
tests.sentry.models.test_projectcounter::test_group_creation_with_stuck_project_counter[ discrepancy = 2 ]
Stack Traces | 6.16s run time
#x1B[1m#x1B[.../sentry/models/test_projectcounter.py#x1B[0m:119: in test_group_creation_with_stuck_project_counter
    assert group_creation_spy.call_count == 2
#x1B[1m#x1B[31mE   AssertionError: assert 1 == 2#x1B[0m
#x1B[1m#x1B[31mE    +  where 1 = <MagicMock id='140224455878912'>.call_count#x1B[0m

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@beezz beezz closed this Nov 11, 2025
@beezz beezz deleted the rm-group-uniq-proj-short-id branch November 11, 2025 14:15
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.

2 participants