remix-run/remix · critical · Error

Migration checksum drift detected for "{row.id}" (journal={r

Error message

Migration checksum drift detected for "{row.id}" (journal={row.checksum}, current={expected})

What it means

A journal row's stored checksum no longer matches the checksum computed from the current migration file. This means an already-applied migration was edited after being applied, so the journal history and the source of truth have diverged; the runner halts the forward run.

Source

Thrown at packages/data-table/src/lib/migrations/runner.ts:117

  for (let row of journal) {
    let migration = migrationMap.get(row.id)

    if (!migration) {
      // Rolling back must stay possible when journal rows have no matching
      // migration files, so only forward runs hard-error on orphaned entries.
      if (direction === 'down') {
        continue
      }

      throw new Error(
        'Applied migration "' + row.id + '_' + row.name + '" is missing from current migrations',
      )
    }

    let expected = await computeChecksum(migration)

    if (expected !== row.checksum) {
      throw new Error(
        'Migration checksum drift detected for "' +
          row.id +
          '" (journal=' +
          row.checksum +
          ', current=' +
          expected +
          ')',
      )
    }
  }
}

function resolveTransactionMode(migration: MigrationDescriptor): MigrationTransactionMode {
  if (migration.transaction) {
    return migration.transaction
  }

  let directive = parseTransactionDirective(migration.up)

View on GitHub (pinned to 9696913134)

Solutions

  1. Revert the edited migration file to its applied content (check git history for the original).
  2. If the edit was intentional, recreate the environment: roll back the migration and re-apply, or drop/rebuild the database in dev.
  3. As a last resort, update the journal row's checksum to the new computed value — only when you are certain the change is safe and all environments get the same file.
  4. Exclude migration files from formatters and normalize line endings (.gitattributes `* text=auto eol=lf`).

Example fix

# before: edited applied migration in place
# 20240101123045_create_users/migration.sql  (modified)

# after: restore original
 git checkout <last-applied-commit> -- path/to/migration.sql
# or (dev only) rebuild from scratch:
#  dropdb && recreatedb && runMigrations up
Defensive patterns

Strategy: try-catch

Validate before calling

for (let row of await db.select().from(journalTable)) {
  let migration = registry.list().find((m) => m.id === row.id)
  if (migration && (await computeChecksum(migration)) !== row.checksum) {
    throw new Error(`file for ${row.id} has drifted from the applied version`)
  }
}

Try / catch

try {
  await runMigrations(db, { direction: 'up' })
} catch (error) {
  if (error instanceof Error && error.message.includes('checksum drift')) {
    // diff the file vs git history; restore original or rebuild the database
  }
  throw error
}

Prevention

When it happens

Trigger: Editing a migration file's SQL/content after it was applied and then running `direction: 'up'`; reformatting or line-ending changes that alter the bytes hashed by computeChecksum during assertMigrationIntegrity.

Common situations: Fixing a typo directly in an old migration; a formatter/linter rewriting migration files on save or in CI; inconsistent line endings (CRLF vs LF) across machines.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/3feeec803c8b5ed9. Report an issue: GitHub.