MP024warning

no-enum-value-removal

DROP TYPE destroys the enum and all columns that use it.

operation
Enums
lock taken
ACCESS EXCLUSIVE
remediation
Manual rewrite
category
Data safety

What triggers it

Fires on any DropStmt whose removeType is OBJECT_TYPE — that is, any DROP TYPE statement.

What does not

Any statement that is not a DropStmt, or a DropStmt targeting something other than OBJECT_TYPE (tables, indexes, views, and so on), returns null immediately.

Where it applies

Applies to every PostgreSQL version MigrationPilot targets. It works on the SQL text alone — no database connection needed.

The lock, and what it blocks

The DROP TYPE statement itself is not characterized by a lock in this check — PostgreSQL simply refuses to drop a type still referenced by a column. ACCESS EXCLUSIVE only enters the picture in the safe alternative, at the ALTER COLUMN ... TYPE step that migrates each table to the recreated type.

Why it matters

PostgreSQL has no ALTER TYPE DROP VALUE. Dropping and recreating an enum type fails if any column references it, and CASCADE drops those columns too.

Unsafe, and safe

Flagged

DROP TYPE status;

Safe alternative

-- Enum values cannot be removed in PostgreSQL.
-- Consider using a TEXT column with a CHECK constraint instead.

What it assumes

The check only tests whether removeType equals OBJECT_TYPE — it does not confirm the dropped type is actually an enum, so DROP TYPE on a composite type or domain triggers the same enum-recreation guidance, which does not really apply there.

What backs this rule

Every rule is a claim about PostgreSQL, so it carries what the claim rests on: a handbook chapter that cites the manual, the incidents that put it there, and the version it was last checked against.

Adding a value to an enum is the smallest schema change there is, and it breaks more migration frameworks than anything else in this handbook — because almost every framework wraps migrations in a transaction by default, and this statement has rules about transactions.

verified against
PostgreSQL 17.10
last checked
2026-08-11
confidence
High

What the CLI prints

migrationpilot analyze migration.sql
⚠ [MP024] WARNING (line 1)
  DROP TYPE "status" will destroy the type and fail if any columns use it. PostgreSQL cannot remove individual enum values. The type must be recreated.

  Safe alternative:
  -- Safe enum recreation pattern:
  -- 1. Create the new type:
  --    CREATE TYPE status_new AS ENUM ('value1', 'value2');
  -- 2. Migrate columns (ACCESS EXCLUSIVE lock, rewrites table):
  --    ALTER TABLE <table> ALTER COLUMN <col>
  --      TYPE status_new USING <col>::text::status_new;
  -- 3. Drop the old type:
  --    DROP TYPE status;
  -- 4. Rename:
  --    ALTER TYPE status_new RENAME TO status;

  Why: Dropping an enum type destroys the type and fails if any columns reference it. PostgreSQL cannot remove individual enum values. You must recreate the type and migrate all columns, which requires an ACCESS EXCLUSIVE lock per table.
  Docs: https://migrationpilot.dev/rules/mp024

Generated by running the CLI's own formatter over the flagged example above, so it is the text the tool actually produces. A real run also reports the other rules that fire on the same statement; those blocks are left out here.

Turning it off

For one statement, put a comment on the line before it:

-- migrationpilot-disable MP024
DROP TYPE status;

For the whole project, in .migrationpilotrc.yml — by name or by id:

.migrationpilotrc.yml
rules:
  MP024: false

# or keep it, and downgrade it
rules:
  MP024:
    severity: warning

Try it

Open this rule's flagged example in the playground. It runs in your browser — edit it and watch the finding appear and disappear.

Run MP024 in the playground

Related rules