{"record":{"id":"b584256eeff5e791","repo":"SonarSource/sonarqube","slug":"failed-to-read-content-of-table-schema-migrations","errorCode":null,"errorMessage":"Failed to read content of table SCHEMA_MIGRATIONS","messagePattern":"Failed to read content of table SCHEMA_MIGRATIONS","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"critical","filePath":"server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java","lineNumber":77,"sourceCode":"    }\n  }\n\n  @Override\n  public void stop() {\n    // nothing to do\n  }\n\n  @Override\n  public Optional<Long> getLastMigrationNumber() {\n    try (Connection connection = database.getDataSource().getConnection()) {\n      List<Long> versions = selectVersions(connection);\n\n      if (!versions.isEmpty()) {\n        return Optional.of(versions.get(versions.size() - 1));\n      }\n      return Optional.empty();\n    } catch (SQLException e) {\n      throw new IllegalStateException(\"Failed to read content of table \" + SCHEMA_MIGRATIONS_TABLE, e);\n    }\n  }\n\n  @Override\n  public void done(RegisteredMigrationStep dbMigration) {\n    long migrationNumber = dbMigration.getMigrationNumber();\n    try (Connection connection = database.getDataSource().getConnection();\n      PreparedStatement statement = connection.prepareStatement(\"insert into schema_migrations(version) values (?)\")) {\n\n      statement.setString(1, String.valueOf(migrationNumber));\n      statement.execute();\n      if (!connection.getAutoCommit()) {\n        connection.commit();\n      }\n    } catch (SQLException e) {\n      throw new IllegalStateException(String.format(\"Failed to insert row with value %s in table %s\", migrationNumber, SCHEMA_MIGRATIONS_TABLE), e);\n    }\n  }","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java#L59-L95","documentation":"MigrationHistoryImpl.getLastMigrationNumber reads the SCHEMA_MIGRATIONS table to find the last applied migration version. An SQLException while querying it is wrapped in IllegalStateException \"Failed to read content of table SCHEMA_MIGRATIONS\". This means the migration framework cannot determine which migrations have already been applied.","triggerScenarios":"The SELECT against SCHEMA_MIGRATIONS (called during start/migration bootstrap) throws SQLException — table missing or locked, permission denied, or a connection/SQL failure.","commonSituations":"User lacks SELECT rights on the table; the table was dropped or the schema was partially wiped manually; DB connection dropped mid-migration; an aborted earlier migration left the database locked or in a bad state.","solutions":["Inspect the underlying SQLException cause to identify the exact failure (table missing, permission, lock, connection).","Grant the sonar.jdbc.user SELECT (and generally DDL/DML) rights on the schema, or run migrations as the schema owner.","If the table was manually removed or corrupted, restore it from backup or, for a fresh install, recreate the empty schema and let migrations run from scratch.","Check for database locks/failed transactions from a previous interrupted migration and resolve them before restarting."],"exampleFix":"// before — insufficient privileges\nGRANT CONNECT ON DATABASE sonar TO sonar_user;\n\n// after — grant schema rights so SCHEMA_MIGRATIONS is readable/writable\nGRANT ALL PRIVILEGES ON SCHEMA public TO sonar_user;\nGRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO sonar_user;","handlingStrategy":"try-catch","validationCode":"// pre-migration check\nSELECT to_regclass('public.schema_migrations') IS NOT NULL AS table_exists;\nSELECT has_table_privilege('sonar_user', 'schema_migrations', 'SELECT');","typeGuard":null,"tryCatchPattern":"try {\n  history.getLastMigrationNumber();\n} catch (IllegalStateException e) {\n  // inspect SQLException cause: grant rights, restore table, or rebuild schema\n  LOGGER.error(\"SCHEMA_MIGRATIONS unreadable; cause={}\", e.getCause());\n}","preventionTips":["Run migrations with the schema owner account that has full DDL/DML rights.","Never manually drop or edit SCHEMA_MIGRATIONS; restore from backup instead.","Take a DB snapshot before starting a major-version migration.","Check for locks/failed transactions after any interrupted migration run."],"tags":["database","migration","sql","sonarqube","schema"],"backgroundTag":"sql-query-failed","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}