MP042warningauto-fix

require-index-name

Indexes without explicit names get auto-generated names that are hard to reference.

operation
Indexes
lock taken
no table lock
remediation
Fixed by --fix
category
Types & schema style

What triggers it

An IndexStmt whose idxname is absent or empty. That is the entire condition — the rule reads relation.relname only to build the message. It fires the same way on CONCURRENTLY, on UNIQUE, on any accessMethod, and on partial or expression indexes.

What does not

Any IndexStmt that carries an idxname, which includes every CREATE INDEX IF NOT EXISTS ... form since the grammar requires a name there. ALTER TABLE ... ADD CONSTRAINT ... UNIQUE and ADD PRIMARY KEY build an index but parse as a Constraint inside AlterTableStmt, never as an IndexStmt, so they are outside the rule. Inline UNIQUE in CREATE TABLE likewise.

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

Naming does not change the lock. A plain CREATE INDEX takes SHARE on the table and a CONCURRENTLY one takes SHARE UPDATE EXCLUSIVE, and this rule is indifferent to which — MP001 is the rule that cares. What the missing name costs you is later: DROP INDEX, REINDEX, ALTER TABLE ... ADD CONSTRAINT ... USING INDEX and pg_stat_user_indexes all need a name you can write down.

Why it matters

Auto-generated index names like "users_email_idx" are unpredictable across environments. Explicit names make it easier to reference indexes in maintenance operations and documentation.

Unsafe, and safe

Flagged

CREATE INDEX ON users (email);

Safe alternative

CREATE INDEX idx_users_email ON users (email);

What it assumes

The rule cannot know whether the name PostgreSQL would generate is already taken, so it cannot distinguish a harmless auto-name from one that will collide and get a numeric suffix. It also cannot verify that the name the fixer writes matches what the server would have chosen for anything but a plain column list — fixMP042 deliberately skips expression indexes, because PostgreSQL names those <table>_expr_idx with a collision counter that is not derivable from the file.

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.

CREATE INDEX blocks every write to the table until it finishes.

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

What the CLI prints

migrationpilot analyze migration.sql
⚠ [MP042] WARNING (line 1)
  CREATE INDEX on "users" without an explicit name. Auto-generated names are fragile and hard to reference in future migrations.

  Safe alternative:
  -- Add an explicit index name:
  -- CREATE INDEX idx_users_<column> ON users (...);

  Why: PostgreSQL auto-generates index names like "users_email_idx" but the naming is fragile and can collide. Explicit index names make future migrations clearer (DROP INDEX, REINDEX), improve monitoring (pg_stat_user_indexes), and are required for UNIQUE ... USING INDEX patterns.
  Docs: https://migrationpilot.dev/rules/mp042

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 MP042
CREATE INDEX ON users (email);

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

.migrationpilotrc.yml
rules:
  MP042: false

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

Related rules