The migration rehearsal script failed because migration 20260928200000_add_totp_credentials had SQL syntax errors that were fixed AFTER the migration was already attempted in the rehearsal database.
- Rehearsal script runs
npx prisma migrate deploywhich attempts all pending migrations - Migration
20260928200000_add_totp_credentialshad syntax errors and failed - Prisma recorded the failed state in
_prisma_migrationstable - We fixed the SQL in the migration file
- Running rehearsal again still sees the old failed attempt in the database
This tells Prisma that the migration should be retried.
# Using the helper script:
DATABASE_URL="postgresql://rehearsal_user:rehearsal_password@localhost:5434/rehearsal_db" \
bash scripts/fix-failed-rehearsal.sh 20260928200000_add_totp_credentials
# Or manually:
DATABASE_URL="postgresql://rehearsal_user:rehearsal_password@localhost:5434/rehearsal_db" \
npx prisma migrate resolve --rolled-back 20260928200000_add_totp_credentialsDATABASE_URL="postgresql://rehearsal_user:rehearsal_password@localhost:5434/rehearsal_db" \
bash scripts/rehearse-migration-rollback.shThe migration will now use the fixed SQL.
If marking as rolled back doesn't work, you can completely reset the rehearsal database:
# Drop and recreate the rehearsal database
psql -h localhost -p 5434 -U postgres << 'EOF'
DROP DATABASE IF EXISTS rehearsal_db;
CREATE DATABASE rehearsal_db;
GRANT ALL PRIVILEGES ON DATABASE rehearsal_db TO rehearsal_user;
EOF
# Run rehearsal with fresh database
DATABASE_URL="postgresql://rehearsal_user:rehearsal_password@localhost:5434/rehearsal_db" \
bash scripts/rehearse-migration-rollback.sh- SQL Typos:
"IDIFNOT EXISTS"→IF NOT EXISTS - PostgreSQL Compatibility: Replaced
ADD CONSTRAINT IF NOT EXISTSwith a DO block for compatibility with PostgreSQL < 12
The migration file now contains correct, PostgreSQL-compatible SQL that will work in rehearsal.
If this happens in CI, the pipeline should:
- Mark the failed migration as rolled back
- Re-run the deployment
Add this to your CI script:
#!/bin/bash
set -e
# Try to deploy migrations
if ! npx prisma migrate deploy; then
echo "Migration failed, checking for recoverable failures..."
# Get the last failed migration
FAILED_MIGRATION=$(psql "$DATABASE_URL" -tAc \
"SELECT migration_name FROM _prisma_migrations
WHERE finished_at IS NULL AND rolled_back_at IS NULL
ORDER BY started_at DESC LIMIT 1;" | tr -d '[:space:]')
if [ -n "$FAILED_MIGRATION" ]; then
echo "Marking $FAILED_MIGRATION as rolled back and retrying..."
npx prisma migrate resolve --rolled-back "$FAILED_MIGRATION"
npx prisma migrate deploy
else
exit 1
fi
fiTo avoid this issue in the future:
- Always test migrations locally before committing
- Run rehearsal script before pushing migration changes
- Use proper SQL syntax - avoid shortcuts
- Check PostgreSQL compatibility for the versions you support
- Use idempotent SQL - always use
IF NOT EXISTS/IF EXISTSwhere possible
- Helper Script:
scripts/fix-failed-rehearsal.sh - Rehearsal Script:
scripts/rehearse-migration-rollback.sh - Fixed Migration:
prisma/migrations/20260928200000_add_totp_credentials/