payloadcms/payload · error · Error

Migration ${migration.name} not found locally.

Error message

Migration ${migration.name} not found locally.

What it means

Thrown by `migrateRefresh` (`payload migrate:fresh`-style refresh: roll back all then re-apply) when a migration recorded in the DB has no corresponding local file. Identical root cause to error 172 but triggered during a full refresh: the loop reverses every recorded migration and needs each one's `down` function. A single missing file stops the whole refresh.

Source

Thrown at packages/payload/src/database/migrations/migrateRefresh.ts:34

  const { existingMigrations } = await getMigrations({
    payload,
  })

  const req = await createLocalReq({}, payload)

  if (existingMigrations?.length) {
    payload.logger.info({
      msg: `Rolling back all ${existingMigrations.length} migration(s).`,
    })
    // Reverse order of migrations to rollback
    existingMigrations.reverse()

    for (const migration of existingMigrations) {
      try {
        const migrationFile = migrationFiles.find((m) => m.name === migration.name)
        if (!migrationFile) {
          throw new Error(`Migration ${migration.name} not found locally.`)
        }

        payload.logger.info({ msg: `Migrating down: ${migration.name}` })
        const start = Date.now()
        await initTransaction(req)
        const session = payload.db.sessions?.[await req.transactionID!]
        await migrationFile.down({ payload, req, session })
        payload.logger.info({
          msg: `Migrated down:  ${migration.name} (${Date.now() - start}ms)`,
        })
        await payload.delete({
          collection: 'payload-migrations',
          req,
          where: {
            name: {
              equals: migration.name,
            },
          },

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Restore all missing migration files from git so every recorded migration has a `down()`.
  2. If some are intentionally gone, delete their rows from `payload-migrations` before refreshing.
  3. Avoid deleting applied migration files; archive instead.

Example fix

# before: refresh fails on missing file
payload migrate:fresh
# after: restore files, then refresh
git checkout HEAD -- src/migrations/
payload migrate:fresh
Defensive patterns

Strategy: validation

Validate before calling

import { readdir } from 'fs/promises'
const local = new Set((await readdir('./src/migrations')).map(stripExt))
const { docs } = await payload.find({ collection: 'payload-migrations', limit: 0 })
const missing = docs.filter((m) => !local.has(m.name))
if (missing.length) throw new Error(`Cannot refresh; missing files: ${missing.map((m) => m.name).join(', ')}`)

Try / catch

try {
  await payload.db.migrateRefresh()
} catch (err) {
  if (/not found locally/.test((err as Error).message)) {
    // restore all missing files or purge their DB rows before re-running
  }
  throw err
}

Prevention

When it happens

Trigger: Running `payload migrate:refresh`/`fresh` with a migration in the DB whose file was removed; branch switching that drops a previously-applied migration file; a deploy that pruned older migration files.

Common situations: Resetting a staging DB after migration cleanup; onboarding scripts that run refresh against a DB seeded by an older code version.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/7354187e6cc728ff. Report an issue: GitHub.