{"id":"9194a1a4e81c249e","repo":"drizzle-team/drizzle-orm","slug":"failed-to-parse-migration-journalentry-tag-9194a1","errorCode":null,"errorMessage":"Failed to parse migration: ${journalEntry.tag}","messagePattern":"Failed to parse migration: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/op-sqlite/migrator.ts","lineNumber":34,"sourceCode":"\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\n\treturn migrationQueries;\n}\n\nexport async function migrate<TSchema extends Record<string, unknown>>(\n\tdb: OPSQLiteDatabase<TSchema>,\n\tconfig: MigrationConfig,\n) {\n\tconst migrations = await readMigrationFiles(config);\n\treturn db.dialect.migrate(migrations, db.session);\n}\n\ninterface State {\n\tsuccess: boolean;\n\terror?: Error;\n}","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/op-sqlite/migrator.ts#L16-L52","documentation":"An Error `Failed to parse migration: ${journalEntry.tag}` thrown by readMigrationFiles() in drizzle-orm/src/op-sqlite/migrator.ts:34. The surrounding try block only does query.split('--> statement-breakpoint') and pushes a result object; the catch is a broad safety net that converts any unexpected failure during that transform into a named migration error.","triggerScenarios":"For a journal entry whose m{idx} file exists, something inside the parse try-block throws. In practice this is rare because split() does not throw on strings; it would require the migration value to be a non-string (e.g. undefined slipped past the missing-check, or a malformed import that resolves to an object/default) so that .split is undefined or throws.","commonSituations":"A migration import resolved to a module namespace object instead of the SQL string (missing default import, bundler interop issue), so query.split is not a function and throws, which the catch rewraps. Can also appear with corrupted/truncated migration content that breaks downstream assumptions.","solutions":["Check that each migration import is the raw SQL string (default export), not a module object — use `import m0000 from './0000_init.sql'` not `import * as m0000`.","Inspect the actual value of migrations[`m${pad4(idx)}`] for the failing tag — log it before calling migrate().","Re-generate the migration with drizzle-kit if the file content looks corrupt.","Ensure the bundler loads .sql files as plain strings (raw-loader / asset extension config)."],"exampleFix":"// before — namespace import yields an object, query.split is undefined -> throws\nimport * as m0000 from './drizzle/0000_init.sql';\nmigrate(db, { journal, migrations: { m0000 } }); // Failed to parse migration: 0000_init\n\n// after — default import gives the SQL string\nimport m0000 from './drizzle/0000_init.sql';\nmigrate(db, { journal, migrations: { m0000 } });","handlingStrategy":"validation","validationCode":"function assertMigrationsAreStrings(migrations: Record<string, unknown>): void {\n  for (const [key, value] of Object.entries(migrations)) {\n    if (typeof value !== 'string') {\n      throw new Error(`Migration ${key} is not a string (got ${typeof value}). Use a default import.`);\n    }\n  }\n}\n\nassertMigrationsAreStrings(migrations);","typeGuard":"function allMigrationsAreStrings(m: Record<string, unknown>): boolean {\n  return Object.values(m).every((v) => typeof v === 'string');\n}","tryCatchPattern":"try {\n  await migrate(db, { journal, migrations });\n} catch (e) {\n  if (e instanceof Error && /Failed to parse migration/i.test(e.message)) {\n    // log the actual value of each migration entry to find the non-string import\n    console.error(migrations);\n  }\n  throw e;\n}","preventionTips":["Use default imports for .sql files so each entry is a string, not a module namespace.","Configure the bundler to load .sql as raw strings.","Validate the migrations map is Record<string, string> before calling migrate()."],"tags":["op-sqlite","migrations","parse","react-native","bundle"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}