Diagnosing Prisma Migrate Migration Conflicts in PostgreSQL
Step‑by‑step diagnostic guide for fixing Prisma Migrate migration conflicts in a Node.js project using PostgreSQL.
26 Aug 2026, 02:34 UTC

Recognizable condition
When you run prisma migrate dev or prisma migrate deploy the command fails with an error similar to:
Migration engine encountered an error: SQL error: duplicate key value violates unique constraint "_prisma_migrations_pkey"
or a generic P2025 error indicating that a migration record is missing or out of order. The useful takeaway is that the migration history stored in the _prisma_migrations table no longer matches the state expected by your Prisma schema, and you need to reconcile the two before proceeding.
Cause / diagnostic table
| Possible cause | What to look for |
|---|---|
| Manual schema changes outside Prisma Migrate | Tables, columns, or indexes added/removed directly in PostgreSQL after the last successful migration. |
| Stale or corrupted migration history | Missing rows, duplicate names, or out‑of‑order applied_at timestamps in _prisma_migrations. |
| Failed migration left partial objects | Some objects created by a migration that errored mid‑run remain in the database. |
| Concurrent migrations on multiple environments | Two CI agents or developers ran migrations at the same time, causing interleaved entries. |
Ordered checks
- Pull the current database schema – run
prisma db pullin your project root (you need read access to the database via theDATABASE_URLin.env). This generates a temporary Prisma schema reflecting what is actually in PostgreSQL. - Inspect the migration table – connect to PostgreSQL (e.g., with
psql $DATABASE_URL) and run:
Look for gaps in theSELECT * FROM _prisma_migrations ORDER BY applied_at;namecolumn, duplicate entries, or missing expected migrations. - Compare schemas – diff the output of
prisma db pullagainst yourschema.prisma. Any differences indicate manual DDL or a failed migration. - Check for leftover objects – if a migration failed, look for tables, columns, or indexes that were partially created (often named with the migration’s prefix). You can list them with:
Replace the pattern as needed.SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND tablename LIKE 'migration_%';
Fixes tied to findings
If manual changes are detected
- Option A: Revert the manual DDL to match
schema.prisma, then rerunprisma migrate dev. - Option B: Import the changes into Prisma by running
prisma db pull, reviewing the pulled schema, copying any wanted alterations intoschema.prisma, and then runningprisma migrate dev --create-onlyto generate a new migration that captures those changes.
If the migration table is corrupted
- Back up your data (e.g.,
pg_dump $DATABASE_URL > backup.sql). - Truncate the history table:
TRUNCATE TABLE _prisma_migrations;(requires write access to the database). - Re‑apply migrations from scratch in a safe environment:
prisma migrate reset(this will drop and recreate all tables – only use on a copy or dev database). - After reset, run
prisma migrate devto replay migrations and verify they apply cleanly.
If a failed migration left partial objects
- Manually drop the incomplete objects (e.g.,
DROP TABLE IF EXISTS incomplete_table;). - Remove the corresponding row from
_prisma_migrationsif it was recorded as applied. - Run
prisma migrate devagain to re‑create the migration cleanly.
If concurrency caused the conflict
- Serialize migration runs: add a file‑based lock or use CI gating (e.g., only allow the main branch to run migrations).
- Ensure each environment has its own database; never point multiple pipelines to the same PostgreSQL instance for migration.
- After resolving the conflict, add a preventive step in your CI config to run
prisma migrate deployonly after acquiring a lock.
Escalation criteria
- If after attempting the above steps the error persists and you cannot identify the source of mismatch.
- If the database contains production data and a reset would cause unacceptable data loss.
- If you need to preserve manual SQL changes that cannot be expressed in Prisma schema.
In these cases, open a Prisma GitHub issue with:
- The full error log from
prisma migrate dev. - A snapshot of your
schema.prisma. - The output of
prisma db pull(the current database schema). - The contents of
_prisma_migrations(you can export withSELECT * FROM _prisma_migrations;).
As a temporary workaround you can run prisma migrate deploy --skip-seed and apply the missing DDL manually via a SQL script, then re‑sync the migration table with prisma migrate resolve --applied <migration-name>.
Verification
- Run
prisma migrate devagain and confirm it finishes without error. - Start Prisma Studio (
prisma studio) and verify that the expected tables, columns, and relations are present. - Check the migration table:
SELECT name FROM _prisma_migrations ORDER BY applied_at;should show a continuous, increasing sequence with no gaps or duplicates. - Optionally, run
prisma db pullonce more and diff the generated schema againstschema.prisma; they should match exactly.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.