SonarSource/sonarqube · critical · java.lang.IllegalStateException
Failed to insert row with value %s in table %s
Error message
Failed to insert row with value %s in table %s
What it means
MigrationHistoryImpl.done records a completed migration by inserting its number into SCHEMA_MIGRATIONS and committing. An SQLException during the insert/commit is wrapped in IllegalStateException "Failed to insert row with value %s in table %s". The migration itself ran, but history could not be persisted, so the migration may be re-applied or the platform halted.
Source
Thrown at server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java:93
return Optional.empty();
} catch (SQLException e) {
throw new IllegalStateException("Failed to read content of table " + SCHEMA_MIGRATIONS_TABLE, e);
}
}
@Override
public void done(RegisteredMigrationStep dbMigration) {
long migrationNumber = dbMigration.getMigrationNumber();
try (Connection connection = database.getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement("insert into schema_migrations(version) values (?)")) {
statement.setString(1, String.valueOf(migrationNumber));
statement.execute();
if (!connection.getAutoCommit()) {
connection.commit();
}
} catch (SQLException e) {
throw new IllegalStateException(String.format("Failed to insert row with value %s in table %s", migrationNumber, SCHEMA_MIGRATIONS_TABLE), e);
}
}
@Override
public long getInitialDbVersion() {
return initialDbVersion;
}
private static List<Long> selectVersions(Connection connection) throws SQLException {
try (Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select version from " + SCHEMA_MIGRATIONS_TABLE)) {
List<Long> res = new ArrayList<>();
while (resultSet.next()) {
res.add(resultSet.getLong(1));
}
return res.stream()
.sorted(Comparator.naturalOrder())
.toList();View on GitHub (pinned to 184c821202)
Solutions
- Check the wrapped SQLException cause to distinguish permissions, missing table, constraint violation, or connection failure.
- Grant the migration user INSERT (ideally full DDL/DML ownership) on the schema and SCHEMA_MIGRATIONS.
- If the table is missing or corrupted, restore it from backup or recreate the schema for a fresh migration run.
- Retry the start after fixing the cause; unrecorded migrations will be re-applied safely if they are idempotent, otherwise restore the DB snapshot taken before migration.
Example fix
// before — read-only user used for migration sonar.jdbc.username=sonar_readonly // after — owner account with write/DDL rights sonar.jdbc.username=sonar_owner
Defensive patterns
Strategy: try-catch
Validate before calling
SELECT has_table_privilege('sonar_user', 'schema_migrations', 'INSERT') AS can_insert;
SELECT NOT pg_is_in_recovery() AS is_writable_primary; Try / catch
try {
history.done(migrationStep);
} catch (IllegalStateException e) {
LOGGER.error("Failed to record migration {}; cause={}", migrationStep.getMigrationNumber(), e.getCause());
throw e;
} Prevention
- Use a writable, privileged account for migrations (not read-only replicas).
- Snapshot the database before migration runs so failures can be rolled back.
- Monitor connection stability during long migrations to avoid mid-write disconnects.
- Verify SCHEMA_MIGRATIONS exists and is writable as part of pre-upgrade checks.
When it happens
Trigger: The INSERT into SCHEMA_MIGRATIONS (or its commit) throws SQLException after a migration step completes — permissions, table missing, constraint conflict, or connection loss during the write.
Common situations: DB user lacks INSERT privileges; SCHEMA_MIGRATIONS dropped or renamed; duplicate migration number from a re-run; connection dropped mid-migration on flaky networks; read-only replicas or restricted accounts used during migration.
Related errors
- Failed to read content of table SCHEMA_MIGRATIONS
- Error during processing of row: [%s]
- Unknown dialect '%s'
- Unsupported dialect id
- Unknown dialect '%s'
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/178d8debd3fbbcbe.
Report an issue: GitHub.