SonarSource/sonarqube · error · IllegalArgumentException

A version event already exists on analysis

Error message

A version event already exists on analysis '%s'

What it means

SonarQube throws this IllegalArgumentException from CreateEventAction.throwException when a client attempts to create a VERSION event on an analysis that already has one. An analysis can hold at most one version event, so the server rejects duplicates with a 400 response. The check runs against existing DB events for the target analysis before insert.

Solutions

  1. Check existing events first (GET api/events?analysis=<uuid>) and skip creation or delete the old version event (POST api/projects/delete_event) before creating a new one.
  2. Make the pipeline step idempotent: catch the 400 and treat 'version already exists' as success.
  3. Ensure each build creates a NEW analysis (e.g. correct CE report) rather than reusing an analysis uuid.

Example fix

// before
callCreateEvent(analysisUuid, "VERSION", "1.2.3"); // fails on retry
// after
List<Event> events = getEvents(analysisUuid);
Event existing = events.stream().filter(e -> "VERSION".equals(e.getCategory())).findFirst().orElse(null);
if (existing != null) {
  deleteEvent(existing.getUuid());
}
callCreateEvent(analysisUuid, "VERSION", "1.2.3");
Defensive patterns

Strategy: validation

Validate before calling

List<Event> events = getEvents(analysisUuid); // GET api/events?analysis=<uuid>
boolean hasVersion = events.stream().anyMatch(e -> "VERSION".equals(e.getCategory()));
if (hasVersion) { /* skip create or delete existing first */ }

Try / catch

try {
  createEvent(analysisUuid, "VERSION", version);
} catch (FeignException | SonarQubeClientException e) {
  if (String.valueOf(e.getMessage()).contains("version event already exists")) {
    LOG.info("version event already present; treating as success");
  } else throw e;
}

Prevention

When it happens

Trigger: POST api/projects/create_event with category=VERSION on an analysis uuid that already has a version event. Calling the API twice for the same analysis (double-click/retry of a non-idempotent call). Automation that publishes a version per build without checking for an existing one.

Common situations: CI pipelines re-running a publish step after a partial failure; scripts using the same analysis uuid; users manually creating a second 'Version' event in the UI for an analysis that already has one.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/projectanalysis/ws/CreateEventAction.java:202

      .ifPresent(throwException(request));
  }

  private static Predicate<EventDto> filterSimilarEvents(CreateEventRequest request) {
    switch (request.getCategory()) {
      case VERSION:
        return dbEvent -> VERSION.getLabel().equals(dbEvent.getCategory());
      case OTHER:
        return dbEvent -> OTHER.getLabel().equals(dbEvent.getCategory()) && request.getName().equals(dbEvent.getName());
      default:
        throw new IllegalStateException("Event category not handled: " + request.getCategory());
    }
  }

  private static Consumer<EventDto> throwException(CreateEventRequest request) {
    switch (request.getCategory()) {
      case VERSION:
        return dbEvent -> {
          throw new IllegalArgumentException(format("A version event already exists on analysis '%s'", request.getAnalysis()));
        };
      case OTHER:
        return dbEvent -> {
          throw new IllegalArgumentException(format("An '%s' event with the same name already exists on analysis '%s'", OTHER.getLabel(), request.getAnalysis()));
        };
      default:
        throw new IllegalStateException("Event category not handled: " + request.getCategory());
    }
  }

  private static class CreateEventRequest {
    private final String analysis;
    private final EventCategory category;
    private final String name;

    private CreateEventRequest(Builder builder) {
      analysis = builder.analysis;
      category = builder.category;

View on GitHub (pinned to 184c821202)