Introduction
Flyway tracks applied migrations in the flyway_schema_history table, storing a checksum of each migration script. When a migration script is modified after being applied (even whitespace changes), Flyway detects the checksum mismatch and refuses to run further migrations with Validate failed: Migrations have failed validation ... Migration checksum mismatch. This is a safety mechanism to prevent silent schema drift, but it blocks deployments when a team member edits an already-applied migration file. The fix requires either repairing the recorded checksum or reverting the migration script to its original state.
Symptoms
org.flywaydb.core.internal.command.DbValidate$1: Validate failed: Migrations have failed validation
Migration checksum mismatch for migration 3
-> Applied to database : 1234567890
-> Resolved locally : 0987654321Or:
FlywayException: Validate failed:
Detected resolved migration not applied to database: 4
-> Migration Description: Add user preferencesCommon Causes
- Migration script edited after deployment: Whitespace, comments, or SQL changes
- Branch merge conflict: Two branches modify the same migration file
- Format changes: Reformatting SQL changes checksum even if logic is same
- Repeatable migration modified unexpectedly: Repeatable migrations should be replaceable
- Manual database changes: Schema modified outside Flyway, causing drift
- Migration number reused: New migration given number already used in history
Step-by-Step Fix
Step 1: Repair checksum for already-applied migrations
```bash # Update Flyway's recorded checksum to match current script flyway repair
# Or with Spring Boot mvn spring-boot:run -Dspring-boot.run.arguments="--flyway.repair=true" ```
Step 2: Create new migration to fix schema drift
```sql -- DO NOT edit V3__add_user_table.sql after it's been applied -- Instead, create a NEW migration:
-- V4__fix_user_table_columns.sql ALTER TABLE users ADD COLUMN IF NOT EXISTS email VARCHAR(255); ALTER TABLE users ALTER COLUMN name SET NOT NULL; ```
Step 3: Handle repeatable migrations correctly
```sql -- Repeatable migrations (R__ prefix) are re-applied when changed -- R__create_views.sql CREATE OR REPLACE VIEW user_summary AS SELECT u.id, u.name, COUNT(o.id) as order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id, u.name;
-- This is SAFE to modify -- Flyway will re-run it -- Flyway tracks repeatable migrations separately from versioned ones ```
Prevention
- Never modify a versioned migration (V#__*.sql) after it has been applied
- Use
flyway repairto update checksums when migration changes are intentional - Create new migrations to fix schema issues rather than editing old ones
- Use repeatable migrations (R__) for views, procedures, and functions that should be replaceable
- Add Flyway validation to CI/CD pipelines to catch checksum mismatches before deployment
- Use version control hooks to prevent edits to already-deployed migration files
- Keep migration scripts immutable -- treat them as append-only records of schema history