{"id":"ae21c173b97b7521","repo":"drizzle-team/drizzle-orm","slug":"missing-migration-journalentry-tag-ae21c1","errorCode":null,"errorMessage":"Missing migration: ${journalEntry.tag}","messagePattern":"Missing migration: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/op-sqlite/migrator.ts","lineNumber":19,"sourceCode":"import { useEffect, useReducer } from 'react';\nimport type { MigrationMeta } from '~/migrator.ts';\nimport type { OPSQLiteDatabase } from './driver.ts';\n\ninterface MigrationConfig {\n\tjournal: {\n\t\tentries: { idx: number; when: number; tag: string; breakpoints: boolean }[];\n\t};\n\tmigrations: Record<string, string>;\n}\n\nasync function readMigrationFiles({ journal, migrations }: MigrationConfig): Promise<MigrationMeta[]> {\n\tconst migrationQueries: MigrationMeta[] = [];\n\n\tfor await (const journalEntry of journal.entries) {\n\t\tconst query = migrations[`m${journalEntry.idx.toString().padStart(4, '0')}`];\n\n\t\tif (!query) {\n\t\t\tthrow new Error(`Missing migration: ${journalEntry.tag}`);\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = query.split('--> statement-breakpoint').map((it) => {\n\t\t\t\treturn it;\n\t\t\t});\n\n\t\t\tmigrationQueries.push({\n\t\t\t\tsql: result,\n\t\t\t\tbps: journalEntry.breakpoints,\n\t\t\t\tfolderMillis: journalEntry.when,\n\t\t\t\thash: '',\n\t\t\t});\n\t\t} catch {\n\t\t\tthrow new Error(`Failed to parse migration: ${journalEntry.tag}`);\n\t\t}\n\t}\n","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/op-sqlite/migrator.ts#L1-L37","documentation":"An Error `Missing migration: ${journalEntry.tag}` thrown by readMigrationFiles() in drizzle-orm/src/op-sqlite/migrator.ts:19. For each journal entry it looks up migrations[`m${pad4(idx)}`]; if that key is absent (no SQL string shipped for that journal index) it throws, naming the migration tag (the human-friendly folder/name) that is missing.","triggerScenarios":"Calling migrate(db, { journal, migrations }) where the journal lists an entry whose corresponding m{idx} file is not present in the migrations map. Common when migration files were not bundled into the React Native app, or when the journal was regenerated but old file imports were dropped.","commonSituations":"Bundling the journal but forgetting to import the generated .sql files; partial migration import after `drizzle-kit generate`; Metro/React Native bundler tree-shaking the migration imports; mismatch between journal entries and shipped migration files after a rename.","solutions":["Ensure every migration file output by drizzle-kit is imported and present in the migrations map passed to migrate().","Verify the journal index matches: for entry idx N, key m + N zero-padded to 4 digits must exist.","Re-run drizzle-kit generate and re-import all produced files; check the bundler is not dropping them.","Co-locate journal + migrations imports so they cannot drift."],"exampleFix":"// before — journal has 3 entries but only 2 files imported\nimport journal from './drizzle/meta/_journal.json';\nimport m0000 from './drizzle/0000_init.sql';\nimport m0001 from './drizzle/0001_users.sql';\nawait migrate(db, { journal, migrations: { m0000, m0001 } }); // throws: Missing migration: 0002_posts\n\n// after — import every generated migration\nimport m0002 from './drizzle/0002_posts.sql';\nawait migrate(db, { journal, migrations: { m0000, m0001, m0002 } });","handlingStrategy":"validation","validationCode":"function assertMigrationsComplete(\n  journal: { entries: { idx: number; tag: string }[] },\n  migrations: Record<string, string>,\n): void {\n  for (const e of journal.entries) {\n    const key = `m${e.idx.toString().padStart(4, '0')}`;\n    if (typeof migrations[key] !== 'string') {\n      throw new Error(`Missing migration file for journal entry ${e.tag} (key ${key})`);\n    }\n  }\n}\n\nassertMigrationsComplete(journal, migrations);","typeGuard":"function isCompleteMigrationMap(\n  journal: { entries: { idx: number }[] },\n  migrations: Record<string, unknown>,\n): boolean {\n  return journal.entries.every((e) =>\n    typeof migrations[`m${e.idx.toString().padStart(4, '0')}`] === 'string',\n  );\n}","tryCatchPattern":null,"preventionTips":["Import every generated migration file as a default string import and add to the migrations map.","Keep journal + migration imports co-located so they cannot drift.","Verify the bundler is not tree-shaking .sql imports."],"tags":["op-sqlite","migrations","react-native","bundle","init"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}