Skip to content

auto-migrate never adds new StrEnum members to an existing Postgres enum type — runtime 'invalid input value for enum' on evolved models #328

Description

@0x054

Summary

auto_migrate=True creates Postgres native enum types for StrEnum fields at table-creation time, but never evolves them: adding a member to the Python StrEnum after the type exists in the database is silently ignored by the migration planner. The first query or insert using the new member then fails at the database with invalid input value for enum <type>: "<value>" — an unhandled exception at runtime, invisible to any test that runs against a freshly-created schema (fresh schemas get the complete enum, so the gap is structurally untestable from the app side).

Repro

  1. Model with class Provider(StrEnum): PLAID = "plaid" and a field provider: Provider; connect(..., auto_migrate=True) — table + provider enum type created with one label.
  2. Add MX = "mx" to the StrEnum. Reconnect with auto_migrate=True against the same database — no DDL is planned.
  3. Model.where(lambda m: m.provider == Provider.MX)invalid input value for enum provider: "mx".

Real-world hit

pinch-backend M13 (syn54x/pinch-backend#93) added MX = "mx" to ConnectionProvider (created in M7 with only plaid). Every test was green — the suite's throwaway schemas always create the enum complete — and every existing database 500s on the first MX request. Found in a local smoke test; production would have hit it on deploy.

Suggested fix

The auto-migrate diff should compare the StrEnum's members against pg_enum for the existing type and emit ALTER TYPE <name> ADD VALUE IF NOT EXISTS '<value>' for each missing label (append-only; PG12+ allows it inside a transaction with the caveat that the new value is unusable until commit — emitting it outside the main migration transaction, or as its own autocommit statement, sidesteps the older-PG restriction entirely). Removed/renamed labels are a genuinely hard problem and can stay out of scope — additive evolution covers the overwhelmingly common case and is what silently breaks today.

Possibly related context: #199 touches enum ADD COLUMN planner divergence (native enum vs varchar resolution), but this issue is about evolving an existing enum type's value set, not column creation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions