TL;DR: Let the migration tool's state table do the dedup - that's what it's for. Read the applied set, fix the cause of the failure (or repair its failed row), and re-run the migrate command. Applied migrations are skipped by version and checksum; only the pending ones run.

The problem as reported:
```text
agent migrated half the tables to the new schema then hit an error - how to re-run safely without double-applying
```

1. Ask the tool what's applied and what's pending: `flyway info`, `alembic current`, `npx prisma migrate status`, `python manage.py showmigrations`, or `rails db:migrate:status`. Expected: two clear lists - applied and pending.
2. Investigate the error on the first pending migration and fix the cause (bad SQL, missing extension, lock timeout, bad data assumption). Expected: a named, fixed root cause - not a retry of the same failure.
3. If the tool recorded a failed row, resolve it before re-running: for prisma, `npx prisma migrate resolve --rolled-back "MIGRATION_NAME"` after manually cleaning partial effects; for flyway, `flyway repair`. Expected: the failed entry is gone and the migration shows as pending again.
4. Re-run the migrate command. Expected: output shows only the pending migrations applying, in order, ending with the database up to date.
5. If the migration moved data, verify with row counts or a schema diff against a known-good environment. Expected: counts match, schema matches.

## Use this when
- A migration run died partway and you're afraid of double-applying.
- You need to resume a half-finished migration safely.
- The tool's state table and your notes disagree - trust the table.

## Not for this skill when
- Migrations are hand-rolled SQL with no state tracking - then there's no dedup to lean on and you need manual bookkeeping.
- The error is a data problem inside an already-applied migration - that's a repair migration, not a resume.

## Variant phrasings
- resume migration without double applying
- migration failed halfway safe to re-run
- will migrate re-run applied migrations
- continue migration after error

## Why it happens
Runners stop at the first error by design, and the applied set is durable in the state table. Re-running is safe because the tool skips what's applied - the fear of double-apply comes from not trusting that mechanism.

## Edge cases
- Non-transactional DDL (MySQL) can leave a migration half-applied with no clean row to repair - reconcile the schema by hand first.
- A migration file edited after it applied: the next run fails checksum validation; ship the change as a new migration.
- Concurrent runners against the same database: use the tool's locking (advisory locks, single runner) so two agents don't interleave.

## Provenance

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