payloadcms/payload · error · Error

Error importing migration file from ${importPath}

Error message

Error importing migration file from ${importPath}

What it means

Thrown by `getPredefinedMigration` when `payload migrate:create` (or create-from-file) is given a `--file` argument whose path contains `/` but fails to import. Because the slash implies a file/package path (not just a migration name), Payload treats the failure as an error rather than silently creating a blank migration. Causes include a missing file, a broken package export, or a migration module that throws on import.

Source

Thrown at packages/payload/src/database/migrations/getPredefinedMigration.ts:81

      })
      process.exit(1)
    }
  } else if (importPath) {
    // Path 2: Any other package or file path - use dynamic import
    // Supports: package.json exports (e.g. @payloadcms/plugin-seo/migration) or absolute file paths
    try {
      const { downSQL, dynamic, imports, upSQL } =
        await dynamicImport<MigrationTemplateArgs>(importPath)
      return {
        downSQL,
        dynamic,
        imports,
        upSQL,
      }
    } catch (_err) {
      if (importPath?.includes('/')) {
        // We can assume that the intent was to import a file, thus we throw an error.
        throw new Error(`Error importing migration file from ${importPath}`)
      }
      // Silently fail. If the migration cannot be imported, it will be created as a blank migration and the import path will be used as the migration name.
      return {}
    }
  }
  return {}
}

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Verify the path exists and is importable (`node -e "import('./src/mig.ts')"` or equivalent).
  2. If pointing at a package subpath, ensure `package.json` `exports` exposes it.
  3. Fix any syntax/runtime errors at the module's top level.
  4. If you only wanted a name (not a file), drop the `/` from the argument so it silently falls back to a blank migration.

Example fix

// before
payload migrate:create myName --file ./src/nonexistent.ts
// after
payload migrate:create myName --file ./src/existing-migration.ts
Defensive patterns

Strategy: try-catch

Validate before calling

import fs from 'fs'
const file = './src/my-migration.ts'
if (file.includes('/') && !fs.existsSync(file)) {
  throw new Error(`Migration source not found: ${file}`)
}

Try / catch

try {
  await runCLI(['migrate:create', name, '--file', file])
} catch (err) {
  if (/Error importing migration file/.test((err as Error).message)) {
    // verify the file exists, has no syntax errors, and is exported correctly
  }
  throw err
}

Prevention

When it happens

Trigger: Running `payload migrate:create myName --file ./src/mig.ts` when the file does not exist or has a syntax error; `--file @somePkg/migration` where the package's export map lacks that subpath; a migration file whose top-level code throws at import time.

Common situations: Sharing a migration across projects via a package path that isn't exported; typos in the `--file` path; ESM/CJS mismatch causing the dynamic import to reject.

Related errors


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