remix-run/remix · error · UsageError
Options --step and --to are mutually exclusive
Error message
Options --step and --to are mutually exclusive
What it means
For remix db migrate, the --step (migrate N steps) and --to (migrate up to a specific migration) options select the migration endpoint and cannot be combined; passing both is rejected.
Source
Thrown at packages/cli/src/lib/commands/db.ts:150
return { command, ...parsed.options }
}
if (command === 'rollback') {
let parsed = parseArgs(
commandArgv,
{
connectionEnv: connectionOption,
dryRun: { flag: '--dry-run', type: 'boolean' },
journalTable: journalOption,
migrations: migrationsOption,
step: { flag: '--step', type: 'string' },
to: { flag: '--to', type: 'string' },
},
{ maxPositionals: 0 },
)
if (parsed.options.step !== undefined && parsed.options.to !== undefined) {
throw invalidOptionValue('Options --step and --to are mutually exclusive')
}
let { step: rawStep, ...options } = parsed.options
return { command, ...options, step: parseStepOption(rawStep) }
}
if (command === 'reset') {
let parsed = parseArgs(
commandArgv,
{
connectionEnv: connectionOption,
force: { flag: '--force', type: 'boolean' },
journalTable: journalOption,
migrations: migrationsOption,
seed: seedOption,
},
{ maxPositionals: 0 },
)View on GitHub (pinned to 9696913134)
Solutions
- Keep only one endpoint option: either --step N or --to <migration-id>
- Drop the irrelevant flag from scripts/CI invocations
- Re-read remix db migrate --help to pick the right selector for the goal
Example fix
# before $ remix db migrate --step 2 --to 0003_add_users # after $ remix db migrate --to 0003_add_users
Defensive patterns
Strategy: validation
Validate before calling
function validMigrateOptions(argv: string[]): boolean {
return !(argv.includes('--step') || argv.some((a) => a.startsWith('--step=')) &&
argv.includes('--to') || argv.some((a) => a.startsWith('--to=')))
} Try / catch
try {
runDbCommand(['migrate', ...flags], context)
} catch (error) {
if (/mutually exclusive/.test(error.message)) failFast('pick --step or --to, not both')
else throw error
} Prevention
- Model endpoint selection as a single variable in scripts (steps OR target)
- Generate migration commands from one source of truth in tooling
- Keep --help output handy when authoring CI migration steps
When it happens
Trigger: parseDbCommandArgs for the migrate branch finds both parsed.options.step and parsed.options.to defined, e.g. remix db migrate --step 2 --to 0003_add_users.
Common situations: Copy-pasting flags from history; scripts that always pass --to and add --step conditionally; misunderstanding that the two are alternative endpoint selectors.
Related errors
- Unknown command: db ${command}
- throw new AssertionError(options)
- ${matcherName} requires a mock function with a .mock.calls p
- throw new AssertionError({ message, actual, expected, operat
- expect(received).toThrow() requires a function (got ${typeof
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/b3c9249859c6cbd0.
Report an issue: GitHub.