payloadcms/payload · warning · Error
Migration aborted: version__status column not found in ${ver
Error message
Migration aborted: version__status column not found in ${versionsTable} table. This migration should only run on schemas that have NOT yet been migrated to per-locale status. If you've already run this migration, no action is needed. What it means
Thrown by migrateSqliteLocalizeStatus as a guard when the `version__status` column does not exist on the target versions table. This migration converts a single global status column into per-locale status rows; absence of `version__status` means the schema has already been migrated (or was never on the old schema), so re-running would be a no-op or destructive. The error message explicitly tells you no action is needed.
Source
Thrown at packages/drizzle/src/sqlite/predefinedMigrations/localize-status/index.ts:80
req,
})
locales = filteredLocaleObjects.map((locale) =>
typeof locale === 'string' ? locale : locale.code,
)
}
payload.logger.info({ msg: `Locales: ${locales.join(', ')}` })
// Check if versions are enabled in config (skip if not)
if (!entityConfig.versions) {
payload.logger.info({
msg: `Skipping migration for ${collectionSlug ? 'collection' : 'global'}: ${entitySlug} - versions not enabled`,
})
return
}
// Validate that version__status column exists before proceeding
if (!(await columnExists({ columnName: 'version__status', db, tableName: versionsTable }))) {
throw new Error(
`Migration aborted: version__status column not found in ${versionsTable} table. ` +
`This migration should only run on schemas that have NOT yet been migrated to per-locale status. ` +
`If you've already run this migration, no action is needed.`,
)
}
const localesTableExists = await tableExists({ db, tableName: localesTable })
if (!localesTableExists) {
// SCENARIO 1: Create the locales table (first localized field in versions)
payload.logger.info({ msg: `Creating new locales table: ${localesTable}` })
await db.run(
sql.raw(`CREATE TABLE "${localesTable}" (
id INTEGER PRIMARY KEY,
_locale TEXT NOT NULL,
_parent_id INTEGER NOT NULL,
version__status TEXT,View on GitHub (pinned to 00c58b35c0)
Solutions
- Treat this error as a successful no-op: the schema is already in the per-locale-status state.
- Track migration completion (e.g. a flag/migration record) so the script does not re-run on the same entity.
- Wrap the call in a try/catch that swallows this specific guard error when you know re-runs are possible.
Example fix
// before
await migrateSqliteLocalizeStatus({ db, payload, collectionSlug: 'posts' })
// after
try {
await migrateSqliteLocalizeStatus({ db, payload, collectionSlug: 'posts' })
} catch (err) {
if (!/version__status column not found/.test(err.message)) throw err
payload.logger.info('localize-status already applied, skipping')
} Defensive patterns
Strategy: try-catch
Try / catch
try {
await migrateSqliteLocalizeStatus({ db, payload, collectionSlug })
} catch (err) {
if (/version__status column not found/.test(err.message)) {
payload.logger.info('localize-status already applied; skipping')
return
}
throw err
} Prevention
- Persist a 'migration applied' record per entity to avoid re-running.
- Treat the 'column not found' error as an idempotency signal, not a real failure.
When it happens
Trigger: Running migrateSqliteLocalizeStatus a second time on an entity that already completed the migration, or against a fresh schema that never had the old `version__status` column.
Common situations: Migration script is not idempotent-tracking and re-runs on every deploy; re-running after a partial failure that already mutated the column.
Related errors
- Either collectionSlug or globalSlug must be provided
- Cannot provide both collectionSlug and globalSlug
- Localization is not enabled in payload config
- ${collectionSlug ? 'Collection' : 'Global'} not found: ${col
- Either collectionSlug or globalSlug must be provided
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/2c66d8b3c6f96b96.
Report an issue: GitHub.