payloadcms/payload · error · Error
Migration ${migration.name} not found locally.
Error message
Migration ${migration.name} not found locally. What it means
Thrown by `migrateDown` (`payload migrate:rollback`) when the `payload-migrations` table records a migration whose name has no matching file in the local migrations directory. Rollback must execute the migration's `down` function, which only exists in the file — so a missing file aborts the rollback. Typically the migration file was deleted, renamed, or the deployed code is behind the DB.
Source
Thrown at packages/payload/src/database/migrations/migrateDown.ts:32
const { existingMigrations, latestBatch } = await getMigrations({
payload,
})
if (!existingMigrations?.length) {
payload.logger.info({ msg: 'No migrations to rollback.' })
return
}
payload.logger.info({
msg: `Rolling back batch ${latestBatch} consisting of ${existingMigrations.length} migration(s).`,
})
const latestBatchMigrations = existingMigrations.filter(({ batch }) => batch === latestBatch)
for (const migration of latestBatchMigrations) {
const migrationFile = migrationFiles.find((m) => m.name === migration.name)
if (!migrationFile) {
throw new Error(`Migration ${migration.name} not found locally.`)
}
const start = Date.now()
const req = await createLocalReq({}, payload)
try {
payload.logger.info({ msg: `Migrating down: ${migrationFile.name}` })
await initTransaction(req)
const session = payload.db.sessions?.[await req.transactionID!]
await migrationFile.down({ payload, req, session })
payload.logger.info({
msg: `Migrated down: ${migrationFile.name} (${Date.now() - start}ms)`,
})
// Waiting for implementation here
await payload.delete({
id: migration.id!,
collection: 'payload-migrations',
req,View on GitHub (pinned to 00c58b35c0)
Solutions
- Restore the missing migration file from version control so its `down()` is available.
- If the rollback is intentionally impossible, manually remove the row from the `payload-migrations` collection/table.
- Keep migration files immutable once applied — never delete applied migrations.
Example fix
# before: migration file deleted, rollback fails payload migrate:rollback # after: restore the file, then rollback git checkout HEAD -- src/migrations/2024_01_01_init.ts payload migrate:rollback
Defensive patterns
Strategy: validation
Validate before calling
import { readdir } from 'fs/promises'
const local = new Set((await readdir('./src/migrations')).map(stripExt))
const recorded = await payload.find({ collection: 'payload-migrations', limit: 0 })
const missing = recorded.docs.filter((m) => !local.has(m.name))
if (missing.length) throw new Error(`Missing local migration files: ${missing.map((m) => m.name).join(', ')}`) Try / catch
try {
await payload.db.migrateDown()
} catch (err) {
if (/not found locally/.test((err as Error).message)) {
// restore the file from git or remove the stray DB row, then retry
}
throw err
} Prevention
- Never delete applied migration files — keep them in version control.
- Before rollback, ensure every DB-recorded migration has a local file.
- If intentionally dropping a migration, also delete its `payload-migrations` row.
When it happens
Trigger: Running `payload migrate:rollback` after deleting a migration file from `src/migrations`; deploying code that no longer ships an older migration that the DB still records; renaming a migration file without re-syncing the DB.
Common situations: Squashing/cleaning up migration files mid-project; CI/CD deploy that pruned old migrations; switching branches where the migration set differs.
Related errors
- Migration ${migration.name} not found locally.
- Error importing migration file from ${importPath}
- Invalid database type given. Valid types are: ${Object.value
- Migration ${migration.name} not found locally.
- Failed to download: ${url}
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/ce44a3d8d86c86ef.
Report an issue: GitHub.