{"record":{"id":"fd9a49591389fd6f","repo":"remix-run/remix","slug":"duplicate-migration-id-migration-id","errorCode":null,"errorMessage":"Duplicate migration id: {migration.id}","messagePattern":"Duplicate migration id: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/data-table/src/lib/migrations/registry.ts","lineNumber":44,"sourceCode":"\n/**\n * Creates an in-memory migration registry.\n * @param initial Optional initial migration list.\n * @returns A migration registry with duplicate-id protection.\n * @example\n * ```ts\n * import { createMigrationRegistry } from 'remix/data-table/migrations'\n *\n * let registry = createMigrationRegistry()\n * registry.register({ id, name, up, down })\n * ```\n */\nexport function createMigrationRegistry(initial: MigrationDescriptor[] = []): MigrationRegistry {\n  let migrations = new Map<string, MigrationDescriptor>()\n\n  for (let migration of initial) {\n    if (migrations.has(migration.id)) {\n      throw new Error('Duplicate migration id: ' + migration.id)\n    }\n\n    migrations.set(migration.id, migration)\n  }\n\n  return {\n    register(migration: MigrationDescriptor) {\n      if (migrations.has(migration.id)) {\n        throw new Error('Duplicate migration id: ' + migration.id)\n      }\n\n      migrations.set(migration.id, migration)\n    },\n    list() {\n      return sortMigrations(Array.from(migrations.values()))\n    },\n  }\n}","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/data-table/src/lib/migrations/registry.ts#L26-L62","documentation":"createMigrationRegistry was initialized with two MigrationDescriptor entries sharing the same `id`. Since ids drive ordering and journal bookkeeping, duplicates are rejected eagerly at registry construction.","triggerScenarios":"Passing an `initial` array (e.g. loaded module descriptors) to createMigrationRegistry where two entries have the same `id` string, often from loading the same directory twice or two migrations generated in the same second.","commonSituations":"Globbing migrations from overlapping directories; a rebase duplicating a migration file; two migrations created within the same timestamp second.","solutions":["Inspect the descriptors passed as `initial` and remove or rename the duplicate id.","Check for the same migration directory being scanned twice by your loader.","If two distinct migrations share a timestamp-second id, regenerate one with a later timestamp and update the journal."],"exampleFix":"// before\ncreateMigrationRegistry([\n  { id: '20240101123045', name: 'create_users', ... },\n  { id: '20240101123045', name: 'add_index', ... },\n])\n\n// after\ncreateMigrationRegistry([\n  { id: '20240101123045', name: 'create_users', ... },\n  { id: '20240101123046', name: 'add_index', ... },\n])","handlingStrategy":"validation","validationCode":"let ids = descriptors.map((m) => m.id)\nif (new Set(ids).size !== ids.length) {\n  let dup = ids.find((id, i) => ids.indexOf(id) !== i)\n  throw new Error('duplicate migration id in input: ' + dup)\n}","typeGuard":"function hasUniqueIds(migrations: MigrationDescriptor[]): boolean {\n  return new Set(migrations.map((m) => m.id)).size === migrations.length\n}","tryCatchPattern":"try {\n  let registry = createMigrationRegistry(all)\n} catch (error) {\n  if (error instanceof Error && error.message.startsWith('Duplicate migration id')) {\n    // dedupe by id, keeping first, then retry\n  }\n  throw error\n}","preventionTips":["Dedupe loaded descriptors by file path and id before constructing the registry.","Treat duplicate ids in a migration set as a CI failure."],"tags":["migrations","duplicate-id","registry"],"backgroundTag":"duplicate-migration-id","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}