{"record":{"id":"823d94b2d802e8f4","repo":"payloadcms/payload","slug":"migration-aborted-version-status-field-not-found","errorCode":null,"errorMessage":"Migration aborted: version._status field not found or has unexpected format in ${versionsCollection}. This migration should only run on schemas that have NOT yet been migrated to per-locale status.","messagePattern":"Migration aborted: version\\._status field not found or has unexpected format in (.+?)\\. This migration should only run on schemas that have NOT yet been migrated to per-locale status\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/db-mongodb/src/predefinedMigrations/migrateLocalizeStatus.ts","lineNumber":168,"sourceCode":"  // Check if _status is already localized\n  if (\n    sampleDoc.version?._status &&\n    typeof sampleDoc.version._status === 'object' &&\n    !Array.isArray(sampleDoc.version._status)\n  ) {\n    payload.logger.info({\n      msg: 'version._status is already localized, migration already completed',\n    })\n    return\n  }\n\n  // Validate that version._status exists and is a string\n  if (\n    !sampleDoc.version ||\n    typeof sampleDoc.version._status !== 'string' ||\n    Array.isArray(sampleDoc.version._status)\n  ) {\n    throw new Error(\n      `Migration aborted: version._status field not found or has unexpected format in ${versionsCollection}. ` +\n        `This migration should only run on schemas that have NOT yet been migrated to per-locale status.`,\n    )\n  }\n\n  payload.logger.info({ msg: 'Fetching all version documents...' })\n\n  // Get all versions, sorted chronologically\n  const allVersions = await connection\n    .collection(versionsCollection)\n    .find({}, { session })\n    .sort({ createdAt: 1, parent: 1 })\n    .toArray()\n\n  payload.logger.info({ msg: `Found ${allVersions.length} version documents` })\n\n  // Transform MongoDB documents to VersionRecord format\n  const versionRecords: VersionRecord[] = allVersions.map((doc: any) => ({","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/db-mongodb/src/predefinedMigrations/migrateLocalizeStatus.ts#L150-L186","documentation":"Before migrating, localizeStatus samples one version document and requires version._status to be a plain string (the pre-migration shape). If version._status is missing, an array, or otherwise non-string, the migration aborts to avoid corrupting data. This protects against running on already-migrated or schema-drifted data.","triggerScenarios":"Running localizeStatus on a versions collection whose sample document lacks version._status (e.g. drafts never produced a status), where _status was already converted to an object (re-running the migration), or where custom code wrote an array/non-string into version._status.","commonSituations":"Re-running the localize-status migration after it already completed; documents created by a custom import that omitted version._status; partial prior migration left the collection half-converted; versions enabled without drafts so _status was never written.","solutions":["If the migration already ran, no action is needed — verify a sample doc shows version._status as an object.","If documents legitimately lack version._status (no drafts), backfill them (e.g. set version._status='draft') or exclude the entity from the migration.","Inspect a sample doc: `db._<slug>_versions.findOne()` and confirm the shape before retrying.","Restore from backup and run the migration once on clean pre-migration data if the collection is in a mixed/half-converted state."],"exampleFix":"// diagnostics — inspect before deciding\n// mongosh\ndb._posts_versions.findOne({}, { 'version._status': 1 })\n\n// if half-converted (mixed string + object), backfill to a clean pre-state or\n// restore from backup, then run migrateLocalizeStatus once.","handlingStrategy":"validation","validationCode":"// Sample the versions collection before invoking the migration\nasync function assertPreMigrationShape(db: any, versionsCollection: string) {\n  const sample = await db.collection(versionsCollection).findOne({})\n  if (!sample) return // nothing to migrate\n  if (typeof sample.version?._status !== 'string') {\n    throw new Error(`${versionsCollection} is not in pre-migration shape (version._status is ${typeof sample.version?._status})`)\n  }\n}","typeGuard":"function isPreMigrationStatus(sample: unknown): sample is { version: { _status: string } } {\n  return typeof sample === 'object' && sample !== null &&\n    typeof (sample as any)?.version?._status === 'string'\n}","tryCatchPattern":"try {\n  await localizeStatus({ collectionSlug, payload, req })\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Migration aborted')) {\n    payload.logger.warn('localize-status already applied or data not in pre-migration shape — skipping')\n    return\n  }\n  throw e\n}","preventionTips":["Run the migration exactly once on clean pre-migration data.","Backfill or exclude entities whose versions legitimately lack version._status.","Sample a document before running to confirm the expected shape.","Back up the database before running schema-shifting migrations."],"tags":["db-mongodb","migration","localization","data-integrity","versions"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}