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
- Upgrade SonarQube so all modules share the same DatabaseMigrationState enum
- Check the MIGRATIONS/migration state in the DB for an unexpected status value
- Restart the server to reset transient migration state
- 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
- Apply upgrades atomically (all nodes/modules same version)
- Poll /api/v2/system/status before invoking migration-status endpoints
- Don't hand-edit migration state in the DB
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
- Invalid message type:
- Unexpected message type:
- unsupported DevOps Platform
- Unsupported WorkersPauseStatus
- a JVM option can't be empty and must start with '-'. The…
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)