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.

Solutions

  1. Add the matching ssl.key setting pointing to the PEM private key for the certificate.
  2. If you intended to use a keystore instead, remove ssl.certificate and set ssl.keystore.path.
  3. 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

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


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/36be70ce0a56174e. Report an issue: GitHub.

Appendix: 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)