## TL;DR
Resolve each failed migration before doing anything else: mark it rolled back if its DDL never landed, or mark it applied if the DDL is already in place. P3009 is Prisma refusing to continue while failed rows sit in _prisma_migrations. Diagnose each one, resolve it with `prisma migrate resolve`, then re-run the migration.

```text
Error: P3009: migrate found failed migrations in the target database, new migrations will not be applied.
```

## Steps

1. List the failed rows: `select migration_name from _prisma_migrations where finished_at is null order by started_at;`.
   Expected: the exact names of the failed migrations, in order.

2. For each failed migration, check whether its DDL actually landed. Open the migration's SQL file and inspect the schema for the objects it creates.
   Expected: per migration, a clear applied or not-applied verdict.

3. If the DDL did not land, mark it rolled back: `prisma migrate resolve --rolled-back "[migration_name]"`.
   Expected: the row is marked rolled back and Prisma will re-apply it on the next run.

4. If the DDL did land (partial success before the failure), mark it applied: `prisma migrate resolve --applied "[migration_name]"`.
   Expected: the row is marked applied without re-running the DDL.

5. Re-run `prisma migrate deploy` (or `migrate dev`).
   Expected: P3009 is gone and the remaining migrations apply cleanly.

## Use this when
- P3009 blocks every migrate command.
- _prisma_migrations has failed rows from a died deploy.
- A migration failed halfway and now nothing new will apply.
- An agent needs the rolled-back versus applied decision explained.

## Not for this skill when
- The error is P3014 shadow database (that is a permissions problem).
- Drift warnings appear on migrate dev with no failed rows.
- Checksums mismatch because a migration file was edited after applying.

## Variant phrasings
- prisma P3009 failed migrations
- migrate found failed migrations how to fix
- prisma migrate resolve rolled back vs applied
- failed migration blocking prisma migrate deploy

## Why it happens
When a migration fails partway, Prisma leaves its _prisma_migrations row in a failed state and refuses to apply anything new until a human resolves it. The resolve step exists because only you can tell whether the failed DDL partially landed; Prisma cannot safely guess, so it stops and waits.

## Edge cases
- Choosing --applied when the DDL did not land corrupts every future diff. Verify first, every time.
- If several migrations failed in a chain, resolve them in order from oldest to newest.
- Never delete rows from _prisma_migrations by hand. The resolve commands keep the bookkeeping consistent; manual deletes do not.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_R1uMQu2t1POkT8rEtMM4Bg
