🐥

Flywayの"Migrations have failed validation"の詳細を調査する

2021/10/28に公開

概要

とあるSpringBoot+Flywayの案件で、Migrations have failed validationのエラーが出力されて、アプリケーションが起動出来なかった。
SpringBootのログにはこれ以上の内容は表示されず、調査が難航した。

このアプリケーションは、いくつかのランドスケープが存在しているが、他の環境ではこの事象は発生していなかった。

この現象を、解決した手順を記載する。

前提条件

  • Flyway version: 7.1.1
  • 調査実行OS: Amazon Linux 2

Flyway Command-line toolをダウンロードする

ソースを直接編集することが出来なかった環境なので、適当なサーバーにFlyway Command-line toolをダウンロードした。

最新バージョンは以下のURLからダウンロード出来る。
https://flywaydb.org/documentation/usage/commandline/

しかしながら、今回はSpringBootで使用しているVersionと合わせるために、maven central repositoryからダウンロードした。
https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline/

$ sudo amazon-linux-extras enable corretto8
$ sudo yum install java-1.8.0-amazon-corretto
$ wget https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline/7.1.1/flyway-commandline-7.1.1-linux-x64.tar.gz
$ tar xvzf flyway-commandline-7.1.1-linux-x64.tar.gz
$ cd flyway-7.1.1

Flyway 設定

以下のようなフォルダ構成になっている。

.
├── conf          ← 設定ファイル
├── drivers
├── jars
├── jre
├── lib
├── licenses
└── sql           ← migration sqlファイル

conf/flyway.confに以下を追記する。

flyway.url=jdbc:postgresql://xxx/yyy
flyway.user=xxx_user
flyway.password=xxxxx
flyway.schemas=public

flyway.table=flyway_schema_history

また、sqlフォルダ以下に、マイグレーションのファイルを配置する。
この状態で、flyway infoを実行すると現在の状況が確認できる。

[ec2-user@xxx flyway-7.1.1]$ ./flyway info
Flyway Community Edition 7.1.1 by Redgate
Database: jdbc:postgresql://jdbc:postgresql://xxx/yyy (PostgreSQL 13.3)
Schema version: 1.01

+-----------+---------+-------------------+------+---------------------+---------+
| Category  | Version | Description       | Type | Installed On        | State   |
+-----------+---------+-------------------+------+---------------------+---------+
| Versioned | 1.00    | table init        | SQL  | 2021-10-12 15:41:34 | Success |
| Versioned | 1.01    | reformat_password | SQL  | 2021-10-19 11:33:38 | Success |
| Versioned | 1.02    | fix field length  | SQL  |                     | Pending |
+-----------+---------+-------------------+------+---------------------+---------+

migrate実行

この状態でmigrateを実行してみる。

[ec2-user@xxx flyway-7.1.1]$ ./flyway migrate
Flyway Community Edition 7.1.1 by Redgate
Database: jdbc:postgresql://jdbc:postgresql://xxx/yyy (PostgreSQL 13.3)
ERROR: Validate failed: Migrations have failed validation

SpringBootのログで出力されていた内容と同様のメッセージが表示される。
ここからなぜValidate failedになるのかを調査していく。

validate実行

https://flywaydb.org/documentation/usage/errorcodes/#validate_error

VALIDATE_ERRORに関するFlywayのドキュメントを見ると、

Caused by: Some migrations have failed validation
Solution: Inspect the list invalidMigrations on the validate result to see the required actions

となっている。
validateを実行すれば原因が判明するかと考えたが、特に出力内容が変わらなかった。

[ec2-user@xxx flyway-7.1.1]$ ./flyway validate
ERROR: Unexpected error
org.flywaydb.core.api.exception.FlywayValidateException: Validate failed: Migrations have failed validation
	at org.flywaydb.core.Flyway$2.execute(Flyway.java:274)
	at org.flywaydb.core.Flyway$2.execute(Flyway.java:266)
	at org.flywaydb.core.Flyway.execute(Flyway.java:538)
	at org.flywaydb.core.Flyway.validate(Flyway.java:266)
	at org.flywaydb.commandline.Main.executeOperation(Main.java:245)
	at org.flywaydb.commandline.Main.main(Main.java:151)

validateのoutputType=jsonを追加して再実行

そこで、validateに関するFlywayのドキュメントを確認してみた。
https://flywaydb.org/documentation/usage/commandline/validate
実行時の引数に、-outputType=jsonがあることが判明。invalidMigrationsが分かりそうなので、この引数を追加して再度実行してみた。

[ec2-user@xxx flyway-7.1.1]$ ./flyway validate -outputType=json
{
  "validationError": "Migrations have failed validation",
  "errorDetails": {
    "errorCode": "VALIDATE_ERROR",
    "errorMessage": "Migrations have failed validation"
  },
  "invalidMigrations": [
    {
      "version": "1.01",
      "description": "reformat_password",
      "filepath": "/xxx/flyway-7.1.1/sql/V1.01__reformat_password.sql",
      "errorDetails": {
        "errorCode": "DESCRIPTION_MISMATCH",
        "errorMessage": "Migration description mismatch for migration version 1.01\n-> Applied to database : reformat_password\n-> Resolved locally    : reformat password. Either revert the changes to the migration, or run repair to update the schema history."
      }
    },
    {
      "version": "1.02",
      "description": "fix field length",
      "filepath": "/xxx/flyway-7.1.1/sql/V1.02__fix_field_length.sql",
      "errorDetails": {
        "errorCode": "RESOLVED_VERSIONED_MIGRATION_NOT_APPLIED",
        "errorMessage": "Detected resolved migration not applied to database: 1.02. To fix this error, either run migrate, or set -ignorePendingMigrations=true."
      }
    }
  ],
  "validationSuccessful": false,
  "validateCount": 0,
  "flywayVersion": "7.1.1",
  "database": "yyy",
  "warnings": [],
  "operation": "validate"
}

上記の出力を見ると、version: 1.01において、DESCRIPTION_MISMATCHになっていることがわかった。開発者に確認したところ、手動で変更してしまった部分があったとのことでした。

まとめ

migrationのエラーが発生し、アプリケーションのログからでは原因が判断出来ない場合は、Flyway Command-line toolを利用すると解決できるはずです。

Discussion