SonarSource/sonarqube · critical · MessageException
Embedded database is not supported in cluster mode
Error message
Embedded database is not supported in cluster mode
What it means
Cluster mode requires an external database. ensureNotH2 (called from checkForApplicationNode) reads sonar.jdbc.url and throws when it is absent, blank, or points to an embedded H2 database (jdbc:h2:). H2 cannot be shared across cluster nodes, so startup is blocked rather than risking data in a non-shared embedded store.
Solutions
- Configure an external database: set sonar.jdbc.url (plus credentials) to PostgreSQL, SQL Server, or Oracle, e.g. jdbc:postgresql://db-host:5432/sonar.
- If the value exists but is wrong, replace the jdbc:h2: URL — any jdbc:h2: prefix is rejected.
- Never leave sonar.jdbc.url empty in cluster mode; a blank value triggers the same error.
Example fix
// before (conf/sonar.properties) sonar.jdbc.url=jdbc:h2:tcp://localhost:9092/sonar // after sonar.jdbc.url=jdbc:postgresql://db.internal:5432/sonar sonar.jdbc.username=sonar sonar.jdbc.password=secret
Defensive patterns
Strategy: validation
Validate before calling
// shell: require an external JDBC URL in cluster mode url=$(grep -E '^sonar\.jdbc\.url=' conf/sonar.properties | cut -d= -f2-) case "$url" in jdbc:h2:*|"") echo "Cluster mode requires an external database (jdbc:postgresql://...)"; exit 1 ;; esac
Prevention
- Always configure PostgreSQL/SQL Server/Oracle before enabling cluster mode
- Never reuse an evaluation H2 configuration in production clusters
- Keep database credentials in a secret store, not hardcoded defaults
When it happens
Trigger: accept() -> checkForApplicationNode -> ensureNotH2 throws when props value of sonar.jdbc.url is null, empty after trim, or starts with 'jdbc:h2:' on an application node with sonar.cluster.enabled=true.
Common situations: Copying a default/evaluation sonar.properties (which uses embedded H2) to a cluster application node; forgetting to configure sonar.jdbc.url entirely; leaving an old H2 URL from a trial install.
Related errors
- Address in property is not a valid address
- Can not connect to database. Please check connectivity and…
- Entries in property must not mix 'host:port' and 'host'…
- Invalid value for property
- Properties [ ] are not allowed when running SonarQube in…
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/a531cca1c1415820.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-main/src/main/java/org/sonar/application/config/ClusterSettings.java:199
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(", "))));
}
}
private void ensureLocalButNotLoopbackAddress(Property property, AddressAndPort addressAndPort) {
String host = addressAndPort.getHost();
if (!network.isLocal(host) || network.isLoopback(host)) {
throw new MessageException(format("Property %s must be a local non-loopback address: %s", property.getKey(), addressAndPort.getHost()));
}View on GitHub (pinned to 184c821202)