SonarSource/sonarqube · error · MessageException

Properties [%s] are not allowed when running SonarQube in cl

Error message

Properties [%s] are not allowed when running SonarQube in cluster mode.

What it means

When SonarQube runs in cluster mode, standalone/Elasticsearch-node settings listed in FORBIDDEN_SEARCH_NODE_SETTINGS are no longer allowed. checkForSearchNode -> ensureNoSearchNodeForbiddenSettings collects every forbidden key that is still set and reports them all in one MessageException, preventing conflicting legacy configuration from silently changing behavior.

Source

Thrown at server/sonar-main/src/main/java/org/sonar/application/config/ClusterSettings.java:191

  private static String requireValue(Props props, Property property) {
    String key = property.getKey();
    String value = props.value(key);
    String trimmedValue = value == null ? null : value.trim();
    if (trimmedValue == null || trimmedValue.isEmpty()) {
      throw new MessageException(format("Property %s is mandatory", key));
    }
    return trimmedValue;
  }

  private static void ensureNoSearchNodeForbiddenSettings(Props props) {
    List<String> violations = FORBIDDEN_SEARCH_NODE_SETTINGS.stream()
      .filter(setting -> props.value(setting.getKey()) != null)
      .map(Property::getKey)
      .toList();

    if (!violations.isEmpty()) {
      throw new MessageException(format("Properties [%s] are not allowed when running SonarQube in cluster mode.", String.join(", ", violations)));
    }
  }

  private static void ensureNotH2(Props props) {
    String jdbcUrl = props.value(JDBC_URL.getKey());
    String trimmedJdbcUrl = jdbcUrl == null ? null : jdbcUrl.trim();
    if (trimmedJdbcUrl == null || trimmedJdbcUrl.isEmpty() || trimmedJdbcUrl.startsWith("jdbc:h2:")) {
      throw new MessageException("Embedded database is not supported in cluster mode");
    }
  }

  private void ensureNotLoopbackAddresses(Property property, Set<AddressAndPort> hostAndPorts) {
    Set<AddressAndPort> loopbackAddresses = hostAndPorts.stream()
      .filter(t -> network.isLoopback(t.getHost()))
      .collect(toSet());
    if (!loopbackAddresses.isEmpty()) {
      throw new MessageException(format("Property %s must not contain a loopback address: %s", property.getKey(),
        loopbackAddresses.stream().map(AddressAndPort::getHost).sorted().collect(Collectors.joining(", "))));

View on GitHub (pinned to 184c821202)

Solutions

  1. Delete every key listed in the error message from conf/sonar.properties on the search node.
  2. Replace legacy search settings with their cluster equivalents (sonar.cluster.search.* properties) where applicable.
  3. Review old provisioning/Ansible/Helm templates that write sonar.search.* keys and strip them for cluster deployments.

Example fix

// before (search node sonar.properties)
sonar.cluster.enabled=true
sonar.search.initialHeapSize=2g

// after (use cluster-appropriate settings only)
sonar.cluster.enabled=true
Defensive patterns

Strategy: validation

Validate before calling

// shell: strip legacy search settings before cluster startup
for key in sonar.search.bootstrapChecks sonar.search.javaOpts sonar.search.port sonar.search.host; do
  grep -q "^${key}=" conf/sonar.properties && echo "Remove $key for cluster mode"
done

Prevention

When it happens

Trigger: checkForSearchNode (for node type 'search') is executed during accept(); it throws when any property in FORBIDDEN_SEARCH_NODE_SETTINGS (legacy local-ES/standalone search settings such as sonar.search.* overrides relevant to clustered search) has a non-null value in props.

Common situations: Migrating a standalone SonarQube installation to a cluster while keeping old sonar.search.* settings in sonar.properties; copying a standalone sonar.properties to a search node; automation templates that still inject removed search-node settings.

Related errors


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