From 5b3822681804a16a88a3086800ed1785c0de2b9c Mon Sep 17 00:00:00 2001 From: NixReaper Date: Fri, 4 Sep 2026 18:48:44 -0500 Subject: [PATCH] Fix duplicate enum type creation in initial migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Postgres ENUM columns auto-create their type as a side effect of the first CREATE TABLE that uses them; since the migration also explicitly pre-creates all 7 enum types up front (to group and control that DDL alongside their explicit drop in downgrade()), the two collided with "type already exists" on the first table past the first enum's owner. create_type=False on each ENUM tells SQLAlchemy the migration manages that DDL itself. Found by running the migration against a real PostgreSQL for the first time (docker compose up on a devbox) — this repo had no Docker/Postgres available to test against when the migration was originally written. Co-Authored-By: Claude Sonnet 5 --- migrations/versions/0001_initial_schema.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/migrations/versions/0001_initial_schema.py b/migrations/versions/0001_initial_schema.py index 04886db..0f4ec00 100644 --- a/migrations/versions/0001_initial_schema.py +++ b/migrations/versions/0001_initial_schema.py @@ -44,6 +44,11 @@ def _timestamps() -> list[sa.Column]: ] +# create_type=False on every enum below: their CREATE TYPE / DROP TYPE DDL +# is issued explicitly in upgrade()/downgrade() instead. Without this, +# SQLAlchemy also tries to auto-create each type as a side effect of the +# first `op.create_table()` that uses a column of that type, colliding with +# the explicit `enum_type.create(...)` call and raising DuplicateObject. MOVIE_STATUS = postgresql.ENUM( "rumored", "planned", @@ -52,6 +57,7 @@ MOVIE_STATUS = postgresql.ENUM( "released", "canceled", name="moviestatus_enum", + create_type=False, ) SERIES_STATUS = postgresql.ENUM( "planned", @@ -61,23 +67,29 @@ SERIES_STATUS = postgresql.ENUM( "ended", "canceled", name="seriesstatus_enum", + create_type=False, ) ARTWORK_TYPE = postgresql.ENUM( "poster", "backdrop", "logo", "profile", "still", "banner", "thumbnail", name="artworktype_enum", + create_type=False, ) VIDEO_TYPE = postgresql.ENUM( "trailer", "teaser", "clip", "featurette", "behind_the_scenes", "interview", "other", name="videotype_enum", + create_type=False, ) COMPANY_TYPE = postgresql.ENUM( - "production_company", "network", "studio", "distributor", name="companytype_enum" + "production_company", "network", "studio", "distributor", name="companytype_enum", + create_type=False, ) INGESTION_JOB_STATUS = postgresql.ENUM( - "pending", "running", "succeeded", "failed", "retrying", name="ingestionjobstatus_enum" + "pending", "running", "succeeded", "failed", "retrying", name="ingestionjobstatus_enum", + create_type=False, ) MATCH_CONFIDENCE = postgresql.ENUM( - "exact", "high", "medium", "low", "ambiguous", "new", name="matchconfidence_enum" + "exact", "high", "medium", "low", "ambiguous", "new", name="matchconfidence_enum", + create_type=False, )