{"record":{"id":"a531cca1c1415820","repo":"SonarSource/sonarqube","slug":"embedded-database-is-not-supported-in-cluster-mode","errorCode":null,"errorMessage":"Embedded database is not supported in cluster mode","messagePattern":"Embedded database is not supported in cluster mode","errorType":"validation","errorClass":"MessageException","httpStatus":null,"severity":"critical","filePath":"server/sonar-main/src/main/java/org/sonar/application/config/ClusterSettings.java","lineNumber":199,"sourceCode":"    return trimmedValue;\n  }\n\n  private static void ensureNoSearchNodeForbiddenSettings(Props props) {\n    List<String> violations = FORBIDDEN_SEARCH_NODE_SETTINGS.stream()\n      .filter(setting -> props.value(setting.getKey()) != null)\n      .map(Property::getKey)\n      .toList();\n\n    if (!violations.isEmpty()) {\n      throw new MessageException(format(\"Properties [%s] are not allowed when running SonarQube in cluster mode.\", String.join(\", \", violations)));\n    }\n  }\n\n  private static void ensureNotH2(Props props) {\n    String jdbcUrl = props.value(JDBC_URL.getKey());\n    String trimmedJdbcUrl = jdbcUrl == null ? null : jdbcUrl.trim();\n    if (trimmedJdbcUrl == null || trimmedJdbcUrl.isEmpty() || trimmedJdbcUrl.startsWith(\"jdbc:h2:\")) {\n      throw new MessageException(\"Embedded database is not supported in cluster mode\");\n    }\n  }\n\n  private void ensureNotLoopbackAddresses(Property property, Set<AddressAndPort> hostAndPorts) {\n    Set<AddressAndPort> loopbackAddresses = hostAndPorts.stream()\n      .filter(t -> network.isLoopback(t.getHost()))\n      .collect(toSet());\n    if (!loopbackAddresses.isEmpty()) {\n      throw new MessageException(format(\"Property %s must not contain a loopback address: %s\", property.getKey(),\n        loopbackAddresses.stream().map(AddressAndPort::getHost).sorted().collect(Collectors.joining(\", \"))));\n    }\n  }\n\n  private void ensureLocalButNotLoopbackAddress(Property property, AddressAndPort addressAndPort) {\n    String host = addressAndPort.getHost();\n    if (!network.isLocal(host) || network.isLoopback(host)) {\n      throw new MessageException(format(\"Property %s must be a local non-loopback address: %s\", property.getKey(), addressAndPort.getHost()));\n    }","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-main/src/main/java/org/sonar/application/config/ClusterSettings.java#L181-L217","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (conf/sonar.properties)\nsonar.jdbc.url=jdbc:h2:tcp://localhost:9092/sonar\n\n// after\nsonar.jdbc.url=jdbc:postgresql://db.internal:5432/sonar\nsonar.jdbc.username=sonar\nsonar.jdbc.password=secret","handlingStrategy":"validation","validationCode":"// shell: require an external JDBC URL in cluster mode\nurl=$(grep -E '^sonar\\.jdbc\\.url=' conf/sonar.properties | cut -d= -f2-)\ncase \"$url\" in\n  jdbc:h2:*|\"\") echo \"Cluster mode requires an external database (jdbc:postgresql://...)\"; exit 1 ;;\nesac","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["database","cluster","h2","configuration"],"backgroundTag":"unsupported-config-value","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}