MP012warningauto-fix

no-enum-add-value-in-transaction

ALTER TYPE ... ADD VALUE cannot run inside a transaction block.

operation
Enums
lock taken
ACCESS EXCLUSIVE
remediation
Fixed by --fix
category
Types & schema style

What triggers it

Fires on any AlterEnumStmt (ALTER TYPE ... ADD VALUE ...) found inside a transaction block, as determined by walking backward for an enclosing BEGIN.

What does not

An AlterEnumStmt running outside any transaction block (in autocommit) never fires, on any PostgreSQL version — the rule only cares whether the statement sits inside BEGIN...COMMIT. Non-AlterEnumStmt statements are skipped too.

Where it applies

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

Behavior genuinely differs by version: before PG 12, ADD VALUE inside a transaction raises a runtime error and fails the migration outright; from PG 12 on it is allowed but still takes ACCESS EXCLUSIVE on the type for the statement.

The lock, and what it blocks

On PG 12+, where this can actually run inside a transaction, PostgreSQL takes ACCESS EXCLUSIVE on the enum type for the duration — short, but enough to block concurrent queries referencing the type. On PG < 12 the statement never gets that far: it raises a runtime error and aborts the transaction instead.

Why it matters

PostgreSQL does not allow adding enum values inside a transaction. If your migration framework wraps statements in BEGIN/COMMIT, this will fail at runtime.

Unsafe, and safe

Flagged

BEGIN;
ALTER TYPE status ADD VALUE 'archived';
COMMIT;

Safe alternative

-- Must run outside a transaction
ALTER TYPE status ADD VALUE 'archived';

Deploy and transaction boundaries

The auto-fix only lifts the statement out of its BEGIN/COMMIT block when it is the first, last, or only statement in it — if other statements in that block must stay transactional, the migration needs restructuring into more than one step.

What it assumes

The rule trusts ctx.pgVersion to reflect the target database's real major version; if that's misconfigured, a migration flagged as an instant PG-12+ lock concern could actually be one that hard-fails at deploy time on an older server, or the reverse.

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
⚠ [MP012] WARNING (line 2)
  ALTER TYPE "status" ADD VALUE 'archived' in a transaction. On PG 12+ this works but takes ACCESS EXCLUSIVE on the enum type. Consider running outside the transaction to minimize lock duration.

  Why: On PostgreSQL versions before 12, ALTER TYPE ADD VALUE inside a transaction raises a runtime error, failing your migration entirely. On PG 12+ it works but takes an ACCESS EXCLUSIVE lock on the type, which can block concurrent queries.
  Docs: https://migrationpilot.dev/rules/mp012

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 MP012
BEGIN;

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

.migrationpilotrc.yml
rules:
  MP012: false

# or keep it, and downgrade it
rules:
  MP012:
    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 MP012 in the playground

Related rules