prisma: Second Prisma migrate run (with no interim schema changes) reports diff and throws "duplicate key" error
Bug description
After introspecting a MySQL database and running an initial migration, and then making no changes of any kind to the schema after that initial introspection, a second run of npx prisma migrate dev incorrectly generates another migration by adding an index already added during that first migration. The second migration then fails to run, reporting a “duplicate key.”

There is nothing special or noteworthy about this particular index: it’s just one of many indices in this DB, and that index name IDX_fileName is unique and exists nowhere else in the database. The syntax in schema.prisma uses exactly the same @@index syntax for this index which is used to create all other indices. The index is not a foreign key but just a regular string column called “fileName”:
fileName String @db.VarChar(1023)
To test this I rolled back the failed migration, deleted the entire migrations folder, removed the failing index from schema.prisma and attempted the same sequence above (npx prisma migrate dev, make no changes to schema, then run npx prisma migrate dev again).
On this second test I see the expected outcome: “Already in sync, no schema change or pending migration was found.” No second migration is generated at all because nothing has changed in the schema.
So I have no idea why this one index (out of hundreds in the DB) causes this behavior, but am curious if it has something to do with this bug fix of a few years ago on an earlier version of Prisma, which mentions oddities surrounding MySql indices.
How to reproduce
- Introspect a MySQL database using
npx prisma db pull - Run the first migration:
npx prisma migrate dev --init - Without making any changes to the schema, run a second migration immediately after the first:
npx prisma migrate dev --second - Verify that a new migration file reporting a diff is (incorrectly) generated, attempting to create an index which was already part of the first migration
Expected behavior
After introspecting the DB and running an initial migration, making no changes of any kind to the schema after that initial introspection, I expect a second run of npx prisma migrate dev not to output any second migration file. Instead the second run should simply log “Already in sync, no schema change or pending migration was found” (because no schema changes have occurred).
Prisma information
(No queries being made yet, this is just an attempt to set up the migrations)
I am not able to share the entire schema but will include the relevant tables below:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model attachment {
id Int @id @default(autoincrement())
createdAt DateTime @default(now()) @db.DateTime(6)
updatedAt DateTime @default(now()) @db.DateTime(6)
deletedAt DateTime? @db.DateTime(6)
lastUserId String? @db.VarChar(60)
fileName String @db.VarChar(1023)
note String? @db.Text
path String @db.VarChar(1023)
type String @db.VarChar(255)
productItemId Int
product_item product_item @relation(fields: [productItemId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "FK_d5749de348b0f64483a3f020046")
@@index([productItemId], map: "FK_d5749de348b0f64483a3f020046")
@@index([deletedAt], map: "IDX_deletedAt")
@@index([fileName], map: "IDX_fileName")
}
model product_item {
id Int @id @default(autoincrement())
uuid String @unique(map: "IDX_2fc7a6ec8c1e67f13f8cf9bffb") @db.VarChar(30)
cost Decimal @default(0.00) @db.Decimal(15, 2)
createdAt DateTime @default(now()) @db.DateTime(6)
updatedAt DateTime @default(now()) @db.DateTime(6)
deletedAt DateTime? @db.DateTime(6)
lastUserId String? @db.VarChar(60)
status String @default("") @db.VarChar(20)
statusNoteId Int? @unique(map: "IDX_ccdae40f3258a45d4883d22f6c")
sequenceNumber Int?
scheduledDate DateTime? @db.Date
componentId Int
component component @relation(fields: [componentId], references: [id], onUpdate: NoAction, map: "FK_eb69e557981ad9e0d5bcb7a78b7")
attachment attachment[]
@@unique([componentId, sequenceNumber], map: "componentId")
@@index([scheduledDate], map: "IDX_SCHEDULEDDATE")
@@index([status], map: "product-item-status-idx")
@@index([uuid], map: "product-item-uuid-idx")
@@index([lastUserId], map: "last-user-id-idx")
}
Environment & setup
- OS: MacOS (Big Sur)
- Database: MySQL
- Node.js version: 12.19.1
Prisma Version
3.5.0
About this issue
- Original URL
- State: open
- Created 3 years ago
- Comments: 24 (16 by maintainers)
I was able to recreate this problem with PostgreSQL 14.1 and prisma 3.8.1 (using extendedIndexes since I wanted to use the Hash index) . Removing the extendedIndexes fixed the problem. Just including the extendedIndexes in the schema file is causing it for some reason.
@feather-michael can you try with prisma@3.8.0-dev.47 (or 3.8.0 stable next week) if the issue still persists?
I’ve tried to reproduce this with a great effort today, with versions 3.5.0 and 3.7.0 and I can’t get the failure; it works as it should.
OS: Linux Db: MySQL versions 8.x and 5.7.x from Docker Prisma 3.5.0 and 3.7.0
Steps taken:
prisma db pulladds all indexesprisma migrate devfinds drift as expected, resets the database and migrates.prisma migrate devfinds no changes.We might need to go this through next week together with @janpio to see if I missed a step or something…
@janpio Thanks very much for the follow-up, I will try to test out your suggested fix later today. I believe I may have initially introspected using version
3.4.2but I reset everything and re-ran the procedure using3.5.0everywhere. I was also prompted to reset the DB on the initial run (the docs seemed to provide a procedure for baselining specifically in production environments, but I wasn’t aware there was an alternative to resetting/losing data when it comes to local development).I will test your fix and update today.