SonarSource/sonarqube · error · MessageException

a JVM option can't overwrite mandatory JVM options. %s overw

Error message

a JVM option can't overwrite mandatory JVM options. %s overwrites %s

What it means

The single-value variant of checkMandatoryOptionOverwrite validates one user-supplied JVM option and throws a MessageException if it would overwrite a mandatory option SonarQube force-sets on the child JVM. The message names both the offending value and the mandatory option (key+value) it would replace.

Source

Thrown at server/sonar-main/src/main/java/org/sonar/application/command/JvmOptions.java:129

   *
   * @throws IllegalArgumentException if argument is empty or does not start with {@code -}.
   */
  public T add(String str) {
    requireNonNull(str, JVM_OPTION_NOT_NULL_ERROR_MESSAGE);
    String value = str.trim();
    if (isInvalidOption(value)) {
      throw new IllegalArgumentException("a JVM option can't be empty and must start with '-'");
    }
    checkMandatoryOptionOverwrite(value);
    options.add(value);

    return castThis();
  }

  private void checkMandatoryOptionOverwrite(String value) {
    Map.Entry<String, String> overriddenMandatoryOption = mandatoryOptionFor(value);
    if (overriddenMandatoryOption != null) {
      throw new MessageException(String.format(
        "a JVM option can't overwrite mandatory JVM options. %s overwrites %s",
        value,
        overriddenMandatoryOption.getKey() + overriddenMandatoryOption.getValue()));
    }
  }

  @CheckForNull
  private Map.Entry<String, String> mandatoryOptionFor(String jvmOption) {
    return mandatoryOptions.entrySet().stream()
      .filter(s -> jvmOption.startsWith(s.getKey()) && !jvmOption.equals(s.getKey() + s.getValue()))
      .findFirst()
      .orElse(null);
  }

  private static boolean isInvalidOption(String value) {
    return value.isEmpty() || !value.startsWith("-");
  }

View on GitHub (pinned to 184c821202)

Solutions

  1. Delete the colliding option from the user JVM options property
  2. Let SonarQube control that setting through its dedicated property (e.g. heap-size properties for Elasticsearch)
  3. Read 'X overwrites Y' in the message to see the reserved option (Y) and remove user option (X)
  4. Re-check the property after SonarQube upgrades, as the set of mandatory options can grow

Example fix

// before
sonar.web.javaOpts=-Xmx1024m -Xms512m
// after (non-reserved flags only)
sonar.web.javaOpts=-XX:+HeapDumpOnOutOfMemoryError
Defensive patterns

Strategy: validation

Validate before calling

boolean conflictsWithMandatory(String opt, Map<String,String> mandatory) {
  return mandatory.keySet().stream().anyMatch(k -> opt.startsWith(k));
}

Try / catch

try {
  launcher.start();
} catch (MessageException e) {
  if (e.getMessage().contains("overwrites")) {
    log.error("User JVM option conflicts with a mandatory option", e);
  }
}

Prevention

When it happens

Trigger: Calling addFromMandatoryProperty with a single JVM option string whose key matches a reserved mandatory option, e.g. passing -Xmx or -Xms where the process heap is managed by SonarQube itself.

Common situations: Hand-tuning child process heap or GC flags that newer SonarQube versions reserve, applying the same javaOpts template to all processes when one process has that option reserved.

Related errors


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