remix-run/remix · error · Error

Cannot combine "to" and "step" migration options in the same

Error message

Cannot combine "to" and "step" migration options in the same run

What it means

The migration runner was given both `to` (a target migration) and `step` (a count) in the same options object. These define conflicting end conditions for the run, so the combination is rejected up front.

Source

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

  migrations: MigrationDescriptor[]
  journalTable: string
  direction: MigrationDirection
  options: MigrationOperationOptions
}

function assertStepOption(step: number | undefined): void {
  if (step === undefined) {
    return
  }

  if (!Number.isInteger(step) || step < 1) {
    throw new Error('Invalid migration step option. Expected a positive integer.')
  }
}

function assertMigrationOperationOptions(options: MigrationOperationOptions): void {
  if (options.to !== undefined && options.step !== undefined) {
    throw new Error('Cannot combine "to" and "step" migration options in the same run')
  }
}

function resolveTargetOption(
  migrations: MigrationDescriptor[],
  to: string | undefined,
): string | undefined {
  if (to === undefined) {
    return undefined
  }

  // Accept either a bare migration id or the full `id_name` directory form and
  // normalize to the bare id so range filtering compares ids consistently.
  let matches = migrations.filter(
    (migration) => migration.id === to || migration.id + '_' + migration.name === to,
  )

  if (matches.length === 0) {

View on GitHub (pinned to 9696913134)

Solutions

  1. Remove one of the two options: either target an id with `to`, or a count with `step`.
  2. If defaults set `step`, override it to `undefined` when specifying `to`: `{ step: undefined, to }`.
  3. Add CLI flag mutual-exclusion checks before invoking the runner.

Example fix

// before
await runMigrations(db, { direction: 'up', to, step })

// after
await runMigrations(db, { direction: 'up', to })
Defensive patterns

Strategy: validation

Validate before calling

if (options.to !== undefined && options.step !== undefined) {
  delete options.step // or reject with a clear CLI error
}

Prevention

When it happens

Trigger: Calling runMigrations with `{ to: '20240101123045_create_users', step: 3 }` — both keys defined triggers assertMigrationOperationOptions inside runMigrationsUnlocked.

Common situations: Spreading a defaults object containing `step` into options that also set `to`; CLI flags `--to X --step N` passed together.

Related errors


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