SonarSource/sonarqube · error · IllegalArgumentException

UNSUPPORTED_DATABASE_MIGRATION_STATUS

Error message

UNSUPPORTED_DATABASE_MIGRATION_STATUS

What it means

IllegalArgumentException thrown by DatabaseMigrationsController.getStatus when databaseMigrationState.getStatus() returns a value not covered by the switch (anything other than RUNNING, FAILED, SUCCEEDED, NONE) on a database whose dialect supports migration. It signals the controller encountered an unknown/legacy migration status enum value.

Solutions

  1. Upgrade SonarQube so all modules share the same DatabaseMigrationState enum
  2. Check the MIGRATIONS/migration state in the DB for an unexpected status value
  3. Restart the server to reset transient migration state
  4. If upgrade is impossible, report the status value to SonarSource support
Defensive patterns

Strategy: retry

Validate before calling

// poll readiness instead of assuming
// GET /api/v2/system/status until UP before calling database-migrations

Try / catch

try {
    resp = api.databaseMigrationsStatus();
} catch (ServerErrorException e) {
    // unexpected migration status: retry with backoff; upgrade server if persistent
}

Prevention

When it happens

Trigger: GET /api/v2/system/database-migrations (or liveness-driven call) while the migration state holds an unmapped status — typically a newly added enum constant not yet handled by this controller, or an unexpected state serialized in the DB.

Common situations: Version mismatch between webapp modules after a partial upgrade, custom patching, or a new SonarQube release adding a status constant while an older controller build is running.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/dbb4dcb84efe93b7. Report an issue: GitHub.

Appendix: source

Thrown at server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/system/controller/DatabaseMigrationsController.java:71

    this.database = database;
  }

  @Operation(summary = "Gets the status of ongoing database migrations, if any", description = "Return the detailed status of ongoing database migrations" +
    " including starting date. If no migration is ongoing or needed it is still possible to call this endpoint and receive appropriate information.")
  @GetMapping
  public DatabaseMigrationsResponse getStatus() {
    Optional<Long> currentVersion = databaseVersion.getVersion();
    checkState(currentVersion.isPresent(), NO_CONNECTION_TO_DB);
    DatabaseVersion.Status status = databaseVersion.getStatus();
    if (status == DatabaseVersion.Status.UP_TO_DATE || status == DatabaseVersion.Status.REQUIRES_DOWNGRADE) {
      return new DatabaseMigrationsResponse(databaseMigrationState);
    } else if (!database.getDialect().supportsMigration()) {
      return new DatabaseMigrationsResponse(DatabaseMigrationState.Status.STATUS_NOT_SUPPORTED);
    } else {
      return switch (databaseMigrationState.getStatus()) {
        case RUNNING, FAILED, SUCCEEDED -> new DatabaseMigrationsResponse(databaseMigrationState);
        case NONE -> new DatabaseMigrationsResponse(DatabaseMigrationState.Status.MIGRATION_REQUIRED);
        default -> throw new IllegalArgumentException(UNSUPPORTED_DATABASE_MIGRATION_STATUS);
      };
    }

  }

  public record DatabaseMigrationsResponse(
    String status,
    @Nullable Integer completedSteps,
    @Nullable Integer totalSteps,
    @Nullable String startedAt,
    @Nullable String message,
    @Nullable String expectedFinishTimestamp) {

    public DatabaseMigrationsResponse(DatabaseMigrationState state) {
      this(state.getStatus().toString(),
        state.getCompletedMigrations(),
        state.getTotalMigrations(),
        state.getStartedAt().map(d -> d.atZone(ZoneOffset.UTC)).map(DateTimeFormatter.ISO_DATE_TIME::format).orElse(null),

View on GitHub (pinned to 184c821202)