Skip to content

ref: fix typing for sentry.db.postgres.base #96694

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

asottile-sentry
Copy link
Member

_set_isolation_level was removed in django/django@64a899d released in django 1.9

_set_isolation_level was removed in django/django@64a899d released in django 1.9
@asottile-sentry asottile-sentry requested a review from a team July 29, 2025 20:49
@asottile-sentry asottile-sentry requested a review from a team as a code owner July 29, 2025 20:49
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Jul 29, 2025
Comment on lines -106 to -108
@auto_reconnect_connection
def _cursor(self, *args, **kwargs):
return super()._cursor()
Copy link
Member Author

Choose a reason for hiding this comment

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

def cursor just calls def _cursor anyway so this should be a tiny simplification

@@ -21,7 +21,7 @@ def inner(self, *args, **kwargs):
raise

self.db.close(reconnect=True)
self.cursor = self.db._cursor()
self.cursor = self.db.cursor()
Copy link
Contributor

Choose a reason for hiding this comment

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

Bug: Auto-Reconnect Cursor Wraps Incorrectly

The auto_reconnect_cursor decorator, when applied to CursorWrapper methods, now incorrectly re-initializes self.cursor to another CursorWrapper instance instead of the raw underlying cursor. This happens because self.db.cursor() returns a CursorWrapper, leading to improper nested wrapping and breaking the CursorWrapper's delegation mechanism.

Locations (1)
Fix in Cursor Fix in Web

Copy link
Member Author

Choose a reason for hiding this comment

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

that's what already happens silly bot

Comment on lines +24 to 25
self.cursor = self.db.cursor()

Copy link
Contributor

Choose a reason for hiding this comment

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

Potential bug: Auto-reconnect logic double-wraps cursors, causing `AttributeError` or recursion when `self.cursor` is reassigned after reconnection.
  • Description: The CursorWrapper expects self.cursor to be the underlying psycopg2 cursor. However, during a database reconnection, the auto_reconnect_cursor decorator at src/sentry/db/postgres/decorators.py:24 assigns self.db.cursor() to self.cursor. Since self.db.cursor() now returns a CursorWrapper, this results in a CursorWrapper containing another CursorWrapper. This double-wrapping can lead to AttributeError exceptions, infinite recursion, or method resolution issues when accessing cursor-specific methods, effectively crashing the application during reconnection events.
  • Suggested fix: Modify the auto_reconnect_cursor decorator to ensure self.cursor is assigned the raw psycopg2 cursor, not another CursorWrapper, after reconnection. This might involve adjusting self.db.cursor()'s behavior or explicitly unwrapping the cursor before assignment to prevent nested wrappers.
    severity: 0.9, confidence: 0.95

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

Copy link
Member Author

Choose a reason for hiding this comment

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

you too, read the original code

Copy link

codecov bot commented Jul 29, 2025

❌ 5 Tests Failed:

Tests completed Failed Passed Skipped
26747 5 26742 600
View the top 3 failed test(s) by shortest run time
tests.sentry.backup.test_rpc.RpcImportRetryTests::test_good_handles_racing_imports
Stack Traces | 0.199s run time
#x1B[1m#x1B[.../sentry/backup/test_rpc.py#x1B[0m:265: in test_good_handles_racing_imports
    assert get_existing_import_chunk_mock.call_count == 2
#x1B[1m#x1B[31mE   AssertionError: assert 1 == 2#x1B[0m
#x1B[1m#x1B[31mE    +  where 1 = <MagicMock id='139908036704448'>.call_count#x1B[0m
tests.sentry.models.test_projectcounter::test_group_creation_with_stuck_project_counter[ discrepancy = 1 ]
Stack Traces | 4.79s run time
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:105: in _execute
    return self.cursor.execute(sql, params)
#x1B[1m#x1B[31mE   psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "sentry_groupedmessage_project_id_short_id_29374dd7_uniq"#x1B[0m
#x1B[1m#x1B[31mE   DETAIL:  Key (project_id, short_id)=(4556501875490817, 1) already exists.#x1B[0m

#x1B[33mThe above exception was the direct cause of the following exception:#x1B[0m
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:91: in inner
    return func(self, sql, *args, **kwargs)
#x1B[1m#x1B[.../db/postgres/base.py#x1B[0m:93: in execute
    return self.cursor.execute(sql, clean_bad_params(params))
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:122: in execute
    return super().execute(sql, params)
#x1B[1m#x1B[31m.venv/lib/python3.13....../site-packages/sentry_sdk/utils.py#x1B[0m:1809: in runner
    return original_function(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:79: in execute
    return self._execute_with_wrappers(
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
#x1B[1m#x1B[.../sentry/testutils/hybrid_cloud.py#x1B[0m:133: in __call__
    return execute(*params)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:100: in _execute
    with self.db.wrap_database_errors:
#x1B[1m#x1B[31m.venv/lib/python3.13.../django/db/utils.py#x1B[0m:91: in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:105: in _execute
    return self.cursor.execute(sql, params)
#x1B[1m#x1B[31mE   django.db.utils.IntegrityError: duplicate key value violates unique constraint "sentry_groupedmessage_project_id_short_id_29374dd7_uniq"#x1B[0m
#x1B[1m#x1B[31mE   DETAIL:  Key (project_id, short_id)=(4556501875490817, 1) already exists.#x1B[0m

#x1B[33mDuring handling of the above exception, another exception occurred:#x1B[0m
#x1B[1m#x1B[.../sentry/models/test_projectcounter.py#x1B[0m:113: in test_group_creation_with_stuck_project_counter
    potentially_stuck_event = save_new_event({"message": new_message}, project)
#x1B[1m#x1B[.../testutils/helpers/eventprocessing.py#x1B[0m:31: in save_new_event
    event = EventManager(event_data).save(project.id)
#x1B[1m#x1B[31m.venv/lib/python3.13........./site-packages/sentry_sdk/tracing_utils.py#x1B[0m:829: in func_with_tracing
    return func(*args, **kwargs)
#x1B[1m#x1B[31msrc/sentry/event_manager.py#x1B[0m:495: in save
    return self.save_error_events(
#x1B[1m#x1B[31m.venv/lib/python3.13........./site-packages/sentry_sdk/tracing_utils.py#x1B[0m:829: in func_with_tracing
    return func(*args, **kwargs)
#x1B[1m#x1B[31msrc/sentry/event_manager.py#x1B[0m:544: in save_error_events
    group_info = assign_event_to_group(event=job["event"], job=job, metric_tags=metric_tags)
#x1B[1m#x1B[31m.venv/lib/python3.13........./site-packages/sentry_sdk/tracing_utils.py#x1B[0m:829: in func_with_tracing
    return func(*args, **kwargs)
#x1B[1m#x1B[31msrc/sentry/event_manager.py#x1B[0m:1313: in assign_event_to_group
    group_info = create_group_with_grouphashes(job, all_grouphashes)
#x1B[1m#x1B[31msrc/sentry/event_manager.py#x1B[0m:1504: in create_group_with_grouphashes
    group = _create_group(project, event, **_get_group_processing_kwargs(job))
#x1B[1m#x1B[31msrc/sentry/event_manager.py#x1B[0m:1575: in _create_group
    group = Group.objects.create(
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1167: in __call__
    return self._mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1171: in _mock_call
    return self._execute_mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1232: in _execute_mock_call
    result = effect(*args, **kwargs)
#x1B[1m#x1B[.../testutils/pytest/mocking.py#x1B[0m:116: in wrapped_fn
    returned_value = fn(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1167: in __call__
    return self._mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1171: in _mock_call
    return self._execute_mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1232: in _execute_mock_call
    result = effect(*args, **kwargs)
#x1B[1m#x1B[.../testutils/pytest/mocking.py#x1B[0m:116: in wrapped_fn
    returned_value = fn(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1167: in __call__
    return self._mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1171: in _mock_call
    return self._execute_mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1232: in _execute_mock_call
    result = effect(*args, **kwargs)
#x1B[1m#x1B[.../testutils/pytest/mocking.py#x1B[0m:116: in wrapped_fn
    returned_value = fn(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1167: in __call__
    return self._mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1171: in _mock_call
    return self._execute_mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1232: in _execute_mock_call
    result = effect(*args, **kwargs)
#x1B[1m#x1B[.../testutils/pytest/mocking.py#x1B[0m:116: in wrapped_fn
    returned_value = fn(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1167: in __call__
    return self._mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1171: in _mock_call
    return self._execute_mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1232: in _execute_mock_call
    result = effect(*args, **kwargs)
#x1B[1m#x1B[.../testutils/pytest/mocking.py#x1B[0m:116: in wrapped_fn
    returned_value = fn(*args, **kwargs)
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/manager.py#x1B[0m:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/query.py#x1B[0m:663: in create
    obj.save(force_insert=True, using=self.db)
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[.../sentry/models/group.py#x1B[0m:667: in save
    super().save(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/base.py#x1B[0m:902: in save
    self.save_base(
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/base.py#x1B[0m:1008: in save_base
    updated = self._save_table(
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/base.py#x1B[0m:1169: in _save_table
    results = self._do_insert(
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/base.py#x1B[0m:1210: in _do_insert
    return manager._insert(
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/manager.py#x1B[0m:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/query.py#x1B[0m:1864: in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
#x1B[1m#x1B[31m.venv/lib/python3.13.../models/sql/compiler.py#x1B[0m:1882: in execute_sql
    cursor.execute(sql, params)
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:77: in inner
    raise_the_exception(self.db, e)
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:75: in inner
    return func(self, *args, **kwargs)
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:18: in inner
    return func(self, *args, **kwargs)
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:93: in inner
    raise type(e)(f"{e!r}\nSQL: {sql}").with_traceback(e.__traceback__)
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:91: in inner
    return func(self, sql, *args, **kwargs)
#x1B[1m#x1B[.../db/postgres/base.py#x1B[0m:93: in execute
    return self.cursor.execute(sql, clean_bad_params(params))
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:122: in execute
    return super().execute(sql, params)
#x1B[1m#x1B[31m.venv/lib/python3.13....../site-packages/sentry_sdk/utils.py#x1B[0m:1809: in runner
    return original_function(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:79: in execute
    return self._execute_with_wrappers(
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
#x1B[1m#x1B[.../sentry/testutils/hybrid_cloud.py#x1B[0m:133: in __call__
    return execute(*params)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:100: in _execute
    with self.db.wrap_database_errors:
#x1B[1m#x1B[31m.venv/lib/python3.13.../django/db/utils.py#x1B[0m:91: in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:105: in _execute
    return self.cursor.execute(sql, params)
#x1B[1m#x1B[31mE   django.db.utils.IntegrityError: IntegrityError('duplicate key value violates unique constraint "sentry_groupedmessage_project_id_short_id_29374dd7_uniq"\nDETAIL:  Key (project_id, short_id)=(4556501875490817, 1) already exists.\n')#x1B[0m
#x1B[1m#x1B[31mE   SQL: INSERT INTO "sentry_groupedmessage" ("project_id", "logger", "level", "message", "view", "num_comments", "platform", "status", "substatus", "times_seen", "last_seen", "first_seen", "first_release_id", "resolved_at", "active_at", "time_spent_total", "time_spent_count", "is_public", "data", "short_id", "type", "priority", "priority_locked_at", "seer_fixability_score", "seer_autofix_last_triggered") VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING "sentry_groupedmessage"."id", "sentry_groupedmessage"."type"#x1B[0m
tests.sentry.models.test_projectcounter::test_group_creation_with_stuck_project_counter[ discrepancy = 3 ]
Stack Traces | 4.97s run time
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:105: in _execute
    return self.cursor.execute(sql, params)
#x1B[1m#x1B[31mE   psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "sentry_groupedmessage_project_id_short_id_29374dd7_uniq"#x1B[0m
#x1B[1m#x1B[31mE   DETAIL:  Key (project_id, short_id)=(4556501877719042, 1) already exists.#x1B[0m

#x1B[33mThe above exception was the direct cause of the following exception:#x1B[0m
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:91: in inner
    return func(self, sql, *args, **kwargs)
#x1B[1m#x1B[.../db/postgres/base.py#x1B[0m:93: in execute
    return self.cursor.execute(sql, clean_bad_params(params))
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:122: in execute
    return super().execute(sql, params)
#x1B[1m#x1B[31m.venv/lib/python3.13....../site-packages/sentry_sdk/utils.py#x1B[0m:1809: in runner
    return original_function(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:79: in execute
    return self._execute_with_wrappers(
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
#x1B[1m#x1B[.../sentry/testutils/hybrid_cloud.py#x1B[0m:133: in __call__
    return execute(*params)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:100: in _execute
    with self.db.wrap_database_errors:
#x1B[1m#x1B[31m.venv/lib/python3.13.../django/db/utils.py#x1B[0m:91: in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:105: in _execute
    return self.cursor.execute(sql, params)
#x1B[1m#x1B[31mE   django.db.utils.IntegrityError: duplicate key value violates unique constraint "sentry_groupedmessage_project_id_short_id_29374dd7_uniq"#x1B[0m
#x1B[1m#x1B[31mE   DETAIL:  Key (project_id, short_id)=(4556501877719042, 1) already exists.#x1B[0m

#x1B[33mDuring handling of the above exception, another exception occurred:#x1B[0m
#x1B[1m#x1B[.../sentry/models/test_projectcounter.py#x1B[0m:113: in test_group_creation_with_stuck_project_counter
    potentially_stuck_event = save_new_event({"message": new_message}, project)
#x1B[1m#x1B[.../testutils/helpers/eventprocessing.py#x1B[0m:31: in save_new_event
    event = EventManager(event_data).save(project.id)
#x1B[1m#x1B[31m.venv/lib/python3.13........./site-packages/sentry_sdk/tracing_utils.py#x1B[0m:829: in func_with_tracing
    return func(*args, **kwargs)
#x1B[1m#x1B[31msrc/sentry/event_manager.py#x1B[0m:495: in save
    return self.save_error_events(
#x1B[1m#x1B[31m.venv/lib/python3.13........./site-packages/sentry_sdk/tracing_utils.py#x1B[0m:829: in func_with_tracing
    return func(*args, **kwargs)
#x1B[1m#x1B[31msrc/sentry/event_manager.py#x1B[0m:544: in save_error_events
    group_info = assign_event_to_group(event=job["event"], job=job, metric_tags=metric_tags)
#x1B[1m#x1B[31m.venv/lib/python3.13........./site-packages/sentry_sdk/tracing_utils.py#x1B[0m:829: in func_with_tracing
    return func(*args, **kwargs)
#x1B[1m#x1B[31msrc/sentry/event_manager.py#x1B[0m:1313: in assign_event_to_group
    group_info = create_group_with_grouphashes(job, all_grouphashes)
#x1B[1m#x1B[31msrc/sentry/event_manager.py#x1B[0m:1504: in create_group_with_grouphashes
    group = _create_group(project, event, **_get_group_processing_kwargs(job))
#x1B[1m#x1B[31msrc/sentry/event_manager.py#x1B[0m:1575: in _create_group
    group = Group.objects.create(
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1167: in __call__
    return self._mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1171: in _mock_call
    return self._execute_mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1232: in _execute_mock_call
    result = effect(*args, **kwargs)
#x1B[1m#x1B[.../testutils/pytest/mocking.py#x1B[0m:116: in wrapped_fn
    returned_value = fn(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1167: in __call__
    return self._mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1171: in _mock_call
    return self._execute_mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1232: in _execute_mock_call
    result = effect(*args, **kwargs)
#x1B[1m#x1B[.../testutils/pytest/mocking.py#x1B[0m:116: in wrapped_fn
    returned_value = fn(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1167: in __call__
    return self._mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1171: in _mock_call
    return self._execute_mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1232: in _execute_mock_call
    result = effect(*args, **kwargs)
#x1B[1m#x1B[.../testutils/pytest/mocking.py#x1B[0m:116: in wrapped_fn
    returned_value = fn(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1167: in __call__
    return self._mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1171: in _mock_call
    return self._execute_mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1232: in _execute_mock_call
    result = effect(*args, **kwargs)
#x1B[1m#x1B[.../testutils/pytest/mocking.py#x1B[0m:116: in wrapped_fn
    returned_value = fn(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1167: in __call__
    return self._mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1171: in _mock_call
    return self._execute_mock_call(*args, **kwargs)
#x1B[1m#x1B[.../hostedtoolcache/Python/3.13.1............................................./x64/lib/python3.13/unittest/mock.py#x1B[0m:1232: in _execute_mock_call
    result = effect(*args, **kwargs)
#x1B[1m#x1B[.../testutils/pytest/mocking.py#x1B[0m:116: in wrapped_fn
    returned_value = fn(*args, **kwargs)
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/manager.py#x1B[0m:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/query.py#x1B[0m:663: in create
    obj.save(force_insert=True, using=self.db)
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[.../sentry/models/group.py#x1B[0m:667: in save
    super().save(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/base.py#x1B[0m:902: in save
    self.save_base(
#x1B[1m#x1B[.../sentry/silo/base.py#x1B[0m:158: in override
    return original_method(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/base.py#x1B[0m:1008: in save_base
    updated = self._save_table(
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/base.py#x1B[0m:1169: in _save_table
    results = self._do_insert(
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/base.py#x1B[0m:1210: in _do_insert
    return manager._insert(
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/manager.py#x1B[0m:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/models/query.py#x1B[0m:1864: in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
#x1B[1m#x1B[31m.venv/lib/python3.13.../models/sql/compiler.py#x1B[0m:1882: in execute_sql
    cursor.execute(sql, params)
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:77: in inner
    raise_the_exception(self.db, e)
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:75: in inner
    return func(self, *args, **kwargs)
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:18: in inner
    return func(self, *args, **kwargs)
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:93: in inner
    raise type(e)(f"{e!r}\nSQL: {sql}").with_traceback(e.__traceback__)
#x1B[1m#x1B[.../db/postgres/decorators.py#x1B[0m:91: in inner
    return func(self, sql, *args, **kwargs)
#x1B[1m#x1B[.../db/postgres/base.py#x1B[0m:93: in execute
    return self.cursor.execute(sql, clean_bad_params(params))
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:122: in execute
    return super().execute(sql, params)
#x1B[1m#x1B[31m.venv/lib/python3.13....../site-packages/sentry_sdk/utils.py#x1B[0m:1809: in runner
    return original_function(*args, **kwargs)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:79: in execute
    return self._execute_with_wrappers(
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
#x1B[1m#x1B[.../sentry/testutils/hybrid_cloud.py#x1B[0m:133: in __call__
    return execute(*params)
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:100: in _execute
    with self.db.wrap_database_errors:
#x1B[1m#x1B[31m.venv/lib/python3.13.../django/db/utils.py#x1B[0m:91: in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
#x1B[1m#x1B[31m.venv/lib/python3.13.../db/backends/utils.py#x1B[0m:105: in _execute
    return self.cursor.execute(sql, params)
#x1B[1m#x1B[31mE   django.db.utils.IntegrityError: IntegrityError('duplicate key value violates unique constraint "sentry_groupedmessage_project_id_short_id_29374dd7_uniq"\nDETAIL:  Key (project_id, short_id)=(4556501877719042, 1) already exists.\n')#x1B[0m
#x1B[1m#x1B[31mE   SQL: INSERT INTO "sentry_groupedmessage" ("project_id", "logger", "level", "message", "view", "num_comments", "platform", "status", "substatus", "times_seen", "last_seen", "first_seen", "first_release_id", "resolved_at", "active_at", "time_spent_total", "time_spent_count", "is_public", "data", "short_id", "type", "priority", "priority_locked_at", "seer_fixability_score", "seer_autofix_last_triggered") VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING "sentry_groupedmessage"."id", "sentry_groupedmessage"."type"#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.

@asottile-sentry asottile-sentry deleted the asottile-db-postgres-base branch August 1, 2025 14:27
@github-actions github-actions bot locked and limited conversation to collaborators Aug 17, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
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