drizzle-team/drizzle-orm · error · Error
Failed to parse migration: ${journalEntry.tag}
Error message
Failed to parse migration: ${journalEntry.tag} What it means
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.
Source
Thrown at drizzle-orm/src/op-sqlite/migrator.ts:34
const query = migrations[`m${journalEntry.idx.toString().padStart(4, '0')}`];
if (!query) {
throw new Error(`Missing migration: ${journalEntry.tag}`);
}
try {
const result = query.split('--> statement-breakpoint').map((it) => {
return it;
});
migrationQueries.push({
sql: result,
bps: journalEntry.breakpoints,
folderMillis: journalEntry.when,
hash: '',
});
} catch {
throw new Error(`Failed to parse migration: ${journalEntry.tag}`);
}
}
return migrationQueries;
}
export async function migrate<TSchema extends Record<string, unknown>>(
db: OPSQLiteDatabase<TSchema>,
config: MigrationConfig,
) {
const migrations = await readMigrationFiles(config);
return db.dialect.migrate(migrations, db.session);
}
interface State {
success: boolean;
error?: Error;
}View on GitHub (pinned to b7862528fd)
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).
Example fix
// before — namespace import yields an object, query.split is undefined -> throws
import * as m0000 from './drizzle/0000_init.sql';
migrate(db, { journal, migrations: { m0000 } }); // Failed to parse migration: 0000_init
// after — default import gives the SQL string
import m0000 from './drizzle/0000_init.sql';
migrate(db, { journal, migrations: { m0000 } }); Defensive patterns
Strategy: validation
Validate before calling
function assertMigrationsAreStrings(migrations: Record<string, unknown>): void {
for (const [key, value] of Object.entries(migrations)) {
if (typeof value !== 'string') {
throw new Error(`Migration ${key} is not a string (got ${typeof value}). Use a default import.`);
}
}
}
assertMigrationsAreStrings(migrations); Type guard
function allMigrationsAreStrings(m: Record<string, unknown>): boolean {
return Object.values(m).every((v) => typeof v === 'string');
} Try / catch
try {
await migrate(db, { journal, migrations });
} catch (e) {
if (e instanceof Error && /Failed to parse migration/i.test(e.message)) {
// log the actual value of each migration entry to find the non-string import
console.error(migrations);
}
throw e;
} Prevention
- 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().
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Missing migration: ${journalEntry.tag}
- Missing migration: ${journalEntry.tag}
- Can't find meta/_journal.json file
- No file ${migrationPath} found in ${migrationFolderTo} folde
AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03).
Data as JSON: /data/errors/9194a1a4e81c249e.json.
Report an issue: GitHub.