SonarSource/sonarqube · error · MessageException

Property %s is mandatory

Error message

Property %s is mandatory

What it means

ClusterSettings.requireValue enforces that a required cluster property has a non-null, non-blank value. It trims the raw value and throws MessageException 'Property %s is mandatory' when the value is missing entirely or contains only whitespace, returning the trimmed value otherwise.

Source

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

    checkValidHosts(property, singleton(addressAndPort));
    return addressAndPort;
  }

  public static NodeType toNodeType(Props props) {
    String nodeTypeValue = requireValue(props, CLUSTER_NODE_TYPE);
    if (!NodeType.isValid(nodeTypeValue)) {
      throw new MessageException(format("Invalid value for property %s: [%s], only [%s] are allowed", CLUSTER_NODE_TYPE.getKey(), nodeTypeValue,
        Arrays.stream(NodeType.values()).map(NodeType::getValue).collect(joining(", "))));
    }
    return NodeType.parse(nodeTypeValue);
  }

  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();

View on GitHub (pinned to 184c821202)

Solutions

  1. Set the property named in the message to a concrete value in conf/sonar.properties (e.g. sonar.cluster.node.host=<this node's IP>).
  2. Remove trailing/leading whitespace-only values and re-enter the value; an empty or blank value is treated as missing.
  3. If this node should not be clustered, disable clustering instead (sonar.cluster.enabled=false) so the check is skipped.

Example fix

// before (conf/sonar.properties)
sonar.cluster.enabled=true
sonar.cluster.node.host=

// after
sonar.cluster.enabled=true
sonar.cluster.node.host=192.168.1.10
Defensive patterns

Strategy: validation

Validate before calling

// shell: fail fast if a required cluster property is blank
for key in sonar.cluster.node.type sonar.cluster.node.host sonar.cluster.search.hosts; do
  v=$(grep -E "^${key}=" conf/sonar.properties | cut -d= -f2 | tr -d ' ')
  [ -z "$v" ] && echo "Property $key is mandatory" && exit 1
done

Prevention

When it happens

Trigger: Called by checkForApplicationNode, hzNodes, searchHost, esHost, clusterNodeHost, and searchHosts whenever a required property such as sonar.cluster.node.type, sonar.cluster.node.host, sonar.cluster.search.hosts, or sonar.cluster.es.hosts is absent or empty during accept() validation.

Common situations: Cluster mode enabled (sonar.cluster.enabled=true) but per-node properties never added; property left as empty placeholder 'sonar.cluster.node.host='; value containing only spaces after an edit; environment-variable substitution that resolved to nothing.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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