drizzle-team/drizzle-orm · critical · Error

Missing migration: ${journalEntry.tag}

Error message

Missing migration: ${journalEntry.tag}

What it means

The durable-sqlite (Durable Object SQLite) migrator reads `journal.entries` and looks up each migration SQL by `m<idx padded to 4>`. If that key is absent from the `migrations` map, the migration file for that journal entry is missing from the bundle and drizzle cannot continue. This halts migration before any statements run.

Source

Thrown at drizzle-orm/src/durable-sqlite/migrator.ts:19

import type { MigrationMeta } from '~/migrator.ts';
import { sql } from '~/sql/index.ts';
import type { DrizzleSqliteDODatabase } from './driver.ts';

interface MigrationConfig {
	journal: {
		entries: { idx: number; when: number; tag: string; breakpoints: boolean }[];
	};
	migrations: Record<string, string>;
}

function readMigrationFiles({ journal, migrations }: MigrationConfig): MigrationMeta[] {
	const migrationQueries: MigrationMeta[] = [];

	for (const journalEntry of journal.entries) {
		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}`);
		}
	}

View on GitHub (pinned to b7862528fd)

Solutions

  1. Regenerate migrations (`drizzle-kit generate`) and confirm every `meta/_journal.json` entry has a matching `m0000`-style file in the migrations folder.
  2. Ensure the `migrations` record passed to `migrate()` is built from the correct folder with all files imported.
  3. If a migration was removed intentionally, also remove its entry from `_journal.json`.

Example fix

// before
migrate(db, { journal, migrations }); // migrations missing m0003
// after - import all generated files
import * as migrations from './drizzle/migrations/*.sql';
migrate(db, { journal, migrations });
Defensive patterns

Strategy: validation

Validate before calling

// Verify every journal entry has a matching migration before migrate()
function assertMigrationsComplete(journal: { entries: { idx: number; tag: string }[] }, migrations: Record<string, string>) {
  for (const e of journal.entries) {
    const key = `m${e.idx.toString().padStart(4, '0')}`;
    if (!migrations[key]) throw new Error(`Missing migration file ${key} (${e.tag})`);
  }
}

Type guard

function isMigrationBundle(j: unknown, m: unknown): j is { entries: { idx: number; tag: string }[] } {
  return !!j && Array.isArray((j as any).entries) && typeof m === 'object' && m !== null;
}

Try / catch

try {
  await migrate(db, { journal, migrations });
} catch (e) {
  const m = (e as Error).message.match(/Missing migration: (.+)/);
  if (m) console.error(`Regenerate or import the file for ${m[1]}`);
  throw e;
}

Prevention

When it happens

Trigger: Calling `migrate(db, { journal, migrations })` for Cloudflare Durable Objects where the `migrations` record is missing one of the `m0000..mNNNN` files referenced by `meta/_journal.json`. Common when the import map/bundler did not include a generated migration file.

Common situations: Forgetting to re-run `drizzle-kit generate` after schema changes and shipping a stale migrations folder, or a glob/import that drops a file (e.g. `.sql` vs no extension mismatch), or referencing a different migrations directory than the one generated.

Related errors


AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03). Data as JSON: /data/errors/57ea2c03233bbd5f.json. Report an issue: GitHub.