elastic/elasticsearch · error · SslConfigException
cannot specify [{}] without also setting [{}]
Error message
cannot specify [{}] without also setting [{}] What it means
buildKeyConfig requires that PEM key material be specified as a pair: ssl.certificate AND ssl.key. Specifying only ssl.certificate means the public cert is present but the private key is missing, so the key manager cannot be built.
Source
Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfigurationLoader.java:389
} else {
return new CompositeTrustConfig(List.of(trustConfig, trust));
}
}
public SslKeyConfig buildKeyConfig(Path basePath) {
final String certificatePath = stringSetting(CERTIFICATE);
final String keyPath = stringSetting(KEY);
final String keyStorePath = stringSetting(KEYSTORE_PATH);
if (certificatePath != null && keyStorePath != null) {
throw new SslConfigException(
"cannot specify both [" + settingPrefix + CERTIFICATE + "] and [" + settingPrefix + KEYSTORE_PATH + "]"
);
}
if (certificatePath != null || keyPath != null) {
if (keyPath == null) {
throw new SslConfigException(
"cannot specify [" + settingPrefix + CERTIFICATE + "] without also setting [" + settingPrefix + KEY + "]"
);
}
if (certificatePath == null) {
throw new SslConfigException(
"cannot specify [" + settingPrefix + KEY + "] without also setting [" + settingPrefix + CERTIFICATE + "]"
);
}
final char[] password = resolvePasswordSetting(KEY_SECURE_PASSPHRASE, KEY_LEGACY_PASSPHRASE);
return new PemKeyConfig(certificatePath, keyPath, password, basePath);
}
if (keyStorePath != null) {
final char[] storePassword = resolvePasswordSetting(KEYSTORE_SECURE_PASSWORD, KEYSTORE_LEGACY_PASSWORD);
char[] keyPassword = resolvePasswordSetting(KEYSTORE_SECURE_KEY_PASSWORD, KEYSTORE_LEGACY_KEY_PASSWORD);
if (keyPassword.length == 0) {
keyPassword = storePassword;
}View on GitHub (pinned to db6a809a66)
Solutions
- Add the matching ssl.key setting pointing to the PEM private key for the certificate.
- If you intended to use a keystore instead, remove ssl.certificate and set ssl.keystore.path.
- Validate that the key matches the cert (openssl x509/pkey modulus compare) after adding it.
Example fix
# before xpack.security.http.ssl.certificate: "node.crt" # after xpack.security.http.ssl.certificate: "node.crt" xpack.security.http.ssl.key: "node.key"
Defensive patterns
Strategy: validation
Validate before calling
void requirePemPair(Map<String,String> settings, String prefix) {
boolean hasCert = settings.containsKey(prefix + "certificate");
boolean hasKey = settings.containsKey(prefix + "key");
if (hasCert && !hasKey)
throw new IllegalArgumentException(prefix + "certificate requires " + prefix + "key");
} Prevention
- Always treat ssl.certificate and ssl.key as a pair in templates.
- Use a config schema that requires both or neither.
- Lint for orphan certificate keys in CI.
When it happens
Trigger: ssl.certificate is set but ssl.key is not, under the same prefix (and ssl.keystore.path is not set as an alternative).
Common situations: Operator sets only the certificate path expecting the key to be auto-discovered; copy-paste that dropped the key line; secret-management system that injects only the cert.
Related errors
- cannot specify both [{}] and [{}]
- failed to load a KeyManager for certificate/key pair [{}], [
- could not load ssl private key file [{}]
- cannot create trust using PEM certificates [{}]
- Error parsing Private Key [{}], file is empty
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/36be70ce0a56174e.
Report an issue: GitHub.