SonarSource/sonarqube · critical · IllegalStateException

Issues changelog export failed after processing %d issue cha

Error message

Issues changelog export failed after processing %d issue changes successfully

What it means

ExportIssuesChangelogStep streams ISSUE_CHANGES rows (oldest first) into ProjectDump.IssueChange protobufs. Any exception during scrolling/conversion/writing is wrapped in an IllegalStateException that includes the count of issue changes exported successfully, to locate the failure point in a large dump.

Source

Thrown at server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectexport/issue/ExportIssuesChangelogStep.java:83

  }

  @Override
  public void execute(Context context) {
    long count = 0;
    try (
      StreamWriter<ProjectDump.IssueChange> output = dumpWriter.newStreamWriter(DumpElement.ISSUES_CHANGELOG);
      DbSession dbSession = dbClient.openSession(false);
      PreparedStatement stmt = createStatement(dbSession);
      ResultSet rs = stmt.executeQuery()) {
      ProjectDump.IssueChange.Builder builder = ProjectDump.IssueChange.newBuilder();
      while (rs.next()) {
        ProjectDump.IssueChange issue = toIssuesChange(builder, rs);
        output.write(issue);
        count++;
      }
      LoggerFactory.getLogger(getClass()).debug("{} issue changes exported", count);
    } catch (Exception e) {
      throw new IllegalStateException(format("Issues changelog export failed after processing %d issue changes successfully", count), e);
    }
  }

  private PreparedStatement createStatement(DbSession dbSession) throws SQLException {
    // export oldest entries first, so they can be imported with smallest ids
    PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(dbSession, QUERY);
    try {
      stmt.setString(1, projectHolder.projectDto().getUuid());
      stmt.setBoolean(2, true);
      stmt.setString(3, STATUS_CLOSED);
      return stmt;
    } catch (Exception t) {
      DatabaseUtils.closeQuietly(stmt);
      throw t;
    }
  }

  private static ProjectDump.IssueChange toIssuesChange(ProjectDump.IssueChange.Builder builder, ResultSet rs) throws SQLException {

View on GitHub (pinned to 184c821202)

Solutions

  1. Examine the wrapped cause (SQLException or protobuf error) and fix the underlying DB/data issue.
  2. Verify schema version matches the SonarQube version; complete any pending migration.
  3. Check connectivity/timeout settings for long-running CE tasks and retry.
  4. Locate the offending changelog row via the logged count and repair it.
Defensive patterns

Strategy: retry

Validate before calling

long changes = dbClient.issueChangeDao().countByProject(projectUuid); // sanity-check accessible rows before export

Try / catch

try {
  exportIssuesChangelogStep.execute(context);
} catch (IllegalStateException e) {
  logger.error("Changelog export failed after {}: {}", parseCount(e.getMessage()), e.getCause(), e);
  throw new JobFailure(e.getCause());
}

Prevention

When it happens

Trigger: SQLException scrolling the issue-changes select; corrupt changelog payload failing protobuf conversion; output.write() IO error; DB connection loss mid-scroll.

Common situations: Very large issue changelogs (long-lived projects) hitting timeouts; corrupt ISSUE_CHANGES data after failed upgrades; connectivity blips during CE export.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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