SonarSource/sonarqube · error · MessageException

a JVM option can't be empty and must start with '-'. The fol

Error message

a JVM option can't be empty and must start with '-'. The following JVM options defined by property '%s' are invalid: %s

What it means

JvmOptions.checkOptionFormat validates JVM options sourced from a SonarQube property before they are applied to a child process. Each option must be non-empty and start with '-'; any entry failing this check causes a MessageException listing the offending values, preventing misconfigured JVM flags from breaking process startup.

Source

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

  public T addFromMandatoryProperty(Props props, String propertyName) {
    String value = props.nonNullValue(propertyName);
    if (!value.isEmpty()) {
      String splitRegex = " (?=-)";
      List<String> jvmOptions = Arrays.stream(value.split(splitRegex)).map(String::trim).toList();
      checkOptionFormat(propertyName, jvmOptions);
      checkMandatoryOptionOverwrite(propertyName, jvmOptions);
      options.addAll(jvmOptions);
    }

    return castThis();
  }

  private static void checkOptionFormat(String propertyName, List<String> jvmOptionsFromProperty) {
    List<String> invalidOptions = jvmOptionsFromProperty.stream()
      .filter(JvmOptions::isInvalidOption)
      .toList();
    if (!invalidOptions.isEmpty()) {
      throw new MessageException(format(
        "a JVM option can't be empty and must start with '-'. The following JVM options defined by property '%s' are invalid: %s",
        propertyName,
        invalidOptions.stream()
          .collect(joining(", "))));
    }
  }

  private void checkMandatoryOptionOverwrite(String propertyName, List<String> jvmOptionsFromProperty) {
    List<Match> matches = jvmOptionsFromProperty.stream()
      .map(jvmOption -> new Match(jvmOption, mandatoryOptionFor(jvmOption)))
      .filter(match -> match.mandatoryOption() != null)
      .toList();
    if (!matches.isEmpty()) {
      throw new MessageException(format(
        "a JVM option can't overwrite mandatory JVM options. The following JVM options defined by property '%s' are invalid: %s",
        propertyName,
        matches.stream()
          .map(m -> m.option() + " overwrites " + m.mandatoryOption.getKey() + m.mandatoryOption.getValue())

View on GitHub (pinned to 184c821202)

Solutions

  1. Prefix every option in the property with '-'; e.g. change Xmx2G to -Xmx2G
  2. Remove empty entries, stray commas and extra whitespace from the property value
  3. Validate the property value with the code below before startup
  4. Restart and confirm the child process JVM receives the corrected options

Example fix

// before
sonar.web.javaOpts=Xmx2G -XX:MaxMetaspaceSize=512M
// after
sonar.web.javaOpts=-Xmx2G -XX:MaxMetaspaceSize=512M
Defensive patterns

Strategy: validation

Validate before calling

List<String> opts = List.of(javaOptsProperty.split("\\s+"));
List<String> bad = opts.stream()
  .filter(o -> o.isEmpty() || !o.startsWith("-"))
  .toList();
if (!bad.isEmpty()) throw new IllegalArgumentException("invalid JVM options: " + bad);

Try / catch

try {
  launcher.start();
} catch (MessageException e) {
  if (e.getMessage().contains("must start with '-'")) {
    log.error("Fix javaOpts property formatting", e);
  }
}

Prevention

When it happens

Trigger: Setting a JVM options property (e.g. sonar.web.javaOpts, sonar.ce.javaOpts, sonar.search.javaOpts) with empty entries, values missing the leading dash (like 'Xmx2G' instead of '-Xmx2G'), or stray spaces/commas producing empty tokens.

Common situations: Copy-pasting JVM flags from documentation without the leading '-', trailing commas or double spaces in the property value, or leaving an empty value that still yields an empty list element after splitting.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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