getsentry / getsentry/self-hosted

Migration error on table `sentry_organizationcontributors` during upgrading to 26.7.1

Open
#4,428 8 comments 2 reactions 0 assignees View on GitHub
Dominant language
Shell
Stars
9.6k
Forks
2k
Avg merge
1d 5h
Merged PRs (30d)
15

Description

You will face two kinds of error:

```
django.db.utils.IntegrityError: check constraint "sentry_organizationcontributors_hostname_6f7999b1_notnull" of relation "sentry_organizationcontributors" is violated by some row

SQL: ALTER TABLE "sentry_organizationcontributors" VALIDATE CONSTRAINT "sentry_organizationcontributors_hostname_6f7999b1_notnull"
```

From the source code, they [described OrganizationContributors](https://github.com/getsentry/sentry/blob/ae93d339a993d4bf41add7ff86567d328bb58e5f/src/sentry/models/organizationcontributors.py#L38-L43) as:
```
Tracks external contributors and their activity for an organization.
This model stores information about contributors associated with an
integration for a specific organization, including their external identity
and how many actions they have taken.
```

The only `INSERT` query is here: https://github.com/getsentry/sentry/blob/ae93d339a993d4bf41add7ff86567d328bb58e5f/src/sentry/seer/code_review/contributor_seats.py#L150-L158

```python
def get_or_create_contributor(
*,
organization: Organization,
integration: Integration | RpcIntegration,
external_identifier: str,
alias: str | None,
) -> OrganizationContributors | None:
"""
TODO(CW-1539): Replace with get_or_create() after the contributor deduplication
migration has completed.
"""
try:
hostname = instance_hostname(integration)
except InstanceHostnameError as e:
sentry_sdk.capture_exception(e)
return None

if contributor := get_canonical_contributor(
organization_id=organization.id,
integration=integration,
external_identifier=external_identifier,
):
return contributor

try:
with transaction.atomic(router.db_for_write(OrganizationContributors)):
return OrganizationContributors.objects.create(
organization_id=organization.id,
integration_id=integration.id,
external_identifier=external_identifier,
provider=integration.provider,
hostname=hostname,
alias=alias,
)
except IntegrityError:
contributor = get_canonical_contributor(
organization_id=organization.id,
integration=integration,
external_identifier=external_identifier,
)
if not contributor:
raise
return contributor
```

For my own case (the second one), the `hostname` fields are empty (null), therefore I need to update each fields to the source code management tool that I use (in this case, GitHub, therefore the value should be "github.com"). Refer to this code: https://github.com/getsentry/sentry/blob/ae93d339a993d4bf41add7ff86567d328bb58e5f/src/sentry/integrations/utils/hostname.py#L10-L32

Therefore the solution for this is changing the value directly on Postgres:
```bash
$ docker compose exec postgres psql -U postgres -d postgres
postgres=# SELECT * FROM sentry_organizationcontributors;

postgres=# UPDATE sentry_organizationcontributors SET hostname = 'github.com';
```

Then re-run `./install.sh`.

---

When you execute it again, you might come across this error:

> I get the following error when upgrading from 26.7.0
>
> ```log
> File "/.venv/lib/python3.13/site-packages/django/db/utils.py", line 91, in __exit__
> raise dj_exc_value.with_traceback(traceback) from exc_value
> File "/.venv/lib/python3.13/site-packages/django/db/backends/utils.py", line 103, in _execute
> return self.cursor.execute(sql)
> ~~~~~~~~~~~~~~~~~~~^^^^^
> File "/usr/src/sentry/src/sentry/db/postgres/decorators.py", line 16, in inner
> return func(self, *args, **kwargs)
> File "/usr/src/sentry/src/sentry/db/postgres/base.py", line 96, in execute
> return self.cursor.execute(sql)
> ~~~~~~~~~~~~~~~~~~~^^^^^
> django.db.utils.ProgrammingError: constraint "sentry_organizationcontributors_hostname_6f7999b1_notnull" for relation "sentry_organizationcontributors" already exists
>
> SQL: ALTER TABLE "sentry_organizationcontributors" ADD CONSTRAINT "sentry_organizationcontributors_hostname_6f7999b1_notnull" CHECK ("hostname" IS NOT NULL) NOT VALID
>
> Error in install/set-up-and-migrate-database.sh:23.
> '$dcr web upgrade --create-kafka-topics' exited with status 1
> -> ./install.sh:main:45
> --> install/set-up-and-migrate-database.sh:source:23
> ```

_Originally posted by @MagnusHBrunbjerg in [#4426](https://github.com/getsentry/self-hosted/issues/4426#issuecomment-5078883739)_

The solution for this is to simply drop the constraint. Execute `\d ` first to ensure the constraint is there. Then just drop it.

```bash
$ docker compose exec postgres psql -U postgres -d postgres
postgres=# \d sentry_organizationcontributors
Table "public.sentry_organizationcontributors"
Column | Type | Collation | Nullable | Default
---------------------+--------------------------+-----------+----------+----------------------------------
id | bigint | | not null | generated by default as identity
integration_id | bigint | | not null |
external_identifier | character varying(255) | | not null |
alias | character varying(255) | | |
num_actions | integer | | not null |
date_added | timestamp with time zone | | not null |
date_updated | timestamp with time zone | | not null |
organization_id | bigint | | not null |
provider | character varying(64) | | |
hostname | character varying(255) | | |
Indexes:
"sentry_organizationcontributors_pkey" PRIMARY KEY, btree (id)
"sentry_oc_org_date_upd_idx" btree (organization_id, date_updated)
"sentry_organizationcontr_external_identifier_ef77d39a_like" btree (external_identifier varchar_pattern_ops)
"sentry_organizationcontributors_external_identifier_ef77d39a" btree (external_identifier)
"sentry_organizationcontributors_integration_id_d13b5795" btree (integration_id)
"sentry_organizationcontributors_organization_id_93cc3a35" btree (organization_id)
"sentry_orgcont_unique_org_cont" UNIQUE CONSTRAINT, btree (organization_id, integration_id, external_identifier)
Check constraints:
"sentry_organizationcontributors_hostname_6f7999b1_notnull" CHECK (hostname IS NOT NULL) NOT VALID
Foreign-key constraints:
"sentry_organizationc_organization_id_93cc3a35_fk_sentry_or" FOREIGN KEY (organization_id) REFERENCES sentry_organization(id) DEFERRABLE INITIALLY DEFERRED
Referenced by:
TABLE "sentry_organizationcontributoraction" CONSTRAINT "sentry_organizationc_organization_contrib_db78e1a3_fk_sentry_or" FOREIGN KEY (organization_contributor_id) REFERENCES sentry_organizationcontributors(id) DEFERRABLE INITIALLY DEFERRED

postgres=# ALTER TABLE sentry_organizationcontributors DROP CONSTRAINT sentry_organizationcontributors_hostname_6f7999b1_notnull;
```

Then re-run `./install.sh`.

---

Oh no, it's still happening!!!

Just truncate it and drop the constraint again.

```bash
$ docker compose exec postgres psql -U postgres -d postgres

postgres=# TRUNCATE TABLE sentry_organizationcontributors CASCADE;

postgres=# ALTER TABLE sentry_organizationcontributors DROP CONSTRAINT sentry_organizationcontributors_provider_4cfc5f3a_notnull;
```

Contributor guide

Open the contributing guide

Research direction

Reproduce the 26.7.0-to-26.7.1 upgrade and start with the migration error for sentry_organizationcontributors. Read src/sentry/models/organizationcontributors.py, src/sentry/seer/code_review/contributor_seats.py, and src/sentry/integrations/utils/hostname.py to trace how hostname values are created. Done means the upgrade completes without invalid or duplicate constraints and without requiring destructive manual database changes.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, docker-compose, postgresql, python
Domain
databases, devops
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.