Spring Boot Flyway Checksum Mismatch and Validate Failed: Repair Guide
I often get asked about Spring Boot freezing on startup with errors like Migration checksum mismatch for migration version 3 or Validate failed: Detected failed migration to version 5. Both indicate Flyway blocking startup during pre-startup validation, but the causes and remedies are completely different. This article covers how to distinguish between the two errors, how to try flyway repair locally, why you should never casually run repair in production, and the steps for manually fixing the flyway_schema_history table — all organized by symptom.
Distinguishing the two error messages
First, read the logs carefully.
ERROR: Migration checksum mismatch for migration version 3
-> Applied to database : -874034534
-> Resolved locally : 1198598178
ERROR: Validate failed: Detected failed migration to version 5 (add_index)
The first is a checksum mismatch. It means the content of an already-applied migration file no longer matches the checksum recorded in the database. The second is a Detected failed migration, indicating that a failed record with success = false remains in flyway_schema_history. In both cases, the Validate process is simply blocking startup, but the underlying causes differ, so first check which log message you’re actually seeing. Sometimes both appear at once.
Typical causes of a changed checksum
The causes of a checksum mismatch generally fall into one of these categories:
- An already-applied migration file (e.g.,
V3__xxx.sql) was edited afterward - Line endings (CRLF/LF) or character encoding changed due to differences in Git configuration or OS
- Migration files are dynamically generated or formatted during CI/CD builds, causing slight content variation on each run
- Upgrading the Flyway version or a plugin changed what gets included in the checksum calculation
The first cause is by far the most common. Even “just fixing a typo” changes the checksum, which is exactly why the rule of never touching an already-applied file matters so much.
First, check the current state with flyway info
Before running repair, objectively check the situation with flyway info.
./gradlew flywayInfo
# or
mvn flyway:info
Looking at the State column in the output tells you which versions are Success, which are Failed, and which are flagged with a checksum mismatch. In production, the first thing you should do is just this info check — do not run repair or migrate, which involve writes, yet.
Trying flyway repair in a local environment
If you know the cause is a local mistake, try repair in your development environment.
./gradlew flywayRepair
# for the Flyway CLI
flyway repair -url=jdbc:postgresql://localhost:5432/mydb -user=dev -password=dev
Comparing flyway info before and after, you’ll see that the version with the checksum mismatch has changed to Success and the failure record has been removed.
What flyway repair actually does
This is the point most people misunderstand. repair only does the following two things:
- Rewrites the checksum in
flyway_schema_historyto match the content of the migration file currently on disk - Deletes failure records where
success = false
In other words, it only makes the file and the database record consistent — it does not check at all whether the actual table structure or data is correct. Since startup succeeds once the checksums match, this command is easy to mistake for something that “fixed” the problem.
Why you should never run repair in production without thinking
Forgetting this nature of repair and running it carelessly in production is dangerous. For example, if V5__add_index.sql failed partway through execution, the actual table might only have half the intended index created. If you run repair in this state, the history gets marked as successful, and the discrepancy from reality (schema drift) is simply hidden. What production actually needs is not aligning the checksum, but actually verifying that the current schema is as intended.
Production recovery procedure
1. Take a backup
Before doing anything, always back up the flyway_schema_history table itself.
CREATE TABLE flyway_schema_history_backup_20260929 AS
SELECT * FROM flyway_schema_history;
If possible, also back up the entire target schema, and keep a log of the flyway info output at this point.
2. Check the table structure
The main columns are as follows.
| Column | Meaning |
|---|---|
installed_rank | Application order |
version | Migration version number |
checksum | Hash value computed from file content |
success | Whether the migration applied successfully |
installed_by | The DB user who ran it |
It’s generally the rows with success = false that are blocking startup.
3. Manually UPDATE/DELETE
Always check the target records first before operating on them.
SELECT * FROM flyway_schema_history WHERE success = false;
-- After visually confirming the actual table, if the partially applied
-- change has already been manually reflected in the DB, delete the failure record
DELETE FROM flyway_schema_history WHERE version = '5' AND success = false;
-- When the file content is correct but only the checksum is out of sync
UPDATE flyway_schema_history
SET checksum = 1198598178
WHERE version = '3';
After running DELETE or UPDATE, always visually verify with SQL that the target tables and columns actually exist before starting the application. Skipping this step means you’d be deploying to production with only the appearance of consistency.
Rules to prevent recurrence
- Never edit an already-applied migration file. Fix issues by adding a new version file instead
- Run
flyway validatein the CI pipeline to detect checksum mismatches before merging - Standardize line endings and character encoding across the entire repository with
.gitattributes
- name: Flyway Validate
run: ./gradlew flywayValidate
Summary
A checksum mismatch is a discrepancy between the file and the database record, while a Detected failed migration is a leftover failure record — the causes are completely different. Repair is convenient, but it only aligns the checksum, so in production always pair it with a flyway info status check and a visual verification of the actual tables. If you want to revisit your Flyway setup from the ground up, see Managing Database Migrations with Flyway in Spring Boot, and for general startup-failure triage, see Diagnosing and Fixing Spring Boot Application Startup Failures. If you’re deciding between Flyway and Liquibase, check out Managing Database Migrations with Liquibase in Spring Boot.