elastic/elasticsearch · error · SslConfigException

cannot specify both [{}] and [{}]

Error message

cannot specify both [{}] and [{}]

What it means

buildTrustConfig refuses configurations that supply both PEM certificate authorities (ssl.certificate_authorities) and a truststore path (ssl.truststore.path). The two are alternative ways to specify trust material; specifying both is ambiguous.

Source

Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfigurationLoader.java:348

            verificationMode,
            clientAuth,
            ciphers,
            protocols,
            handshakeTimeoutMillis
        );
    }

    protected SslTrustConfig buildTrustConfig(
        Path basePath,
        SslVerificationMode verificationMode,
        SslKeyConfig keyConfig,
        @Nullable Set<X509Field> restrictedTrustFields
    ) {
        final List<String> certificateAuthorities = resolveListSetting(CERTIFICATE_AUTHORITIES, Function.identity(), null);
        final String trustStorePath = resolveSetting(TRUSTSTORE_PATH, Function.identity(), null);

        if (certificateAuthorities != null && trustStorePath != null) {
            throw new SslConfigException(
                "cannot specify both [" + settingPrefix + CERTIFICATE_AUTHORITIES + "] and [" + settingPrefix + TRUSTSTORE_PATH + "]"
            );
        }
        if (verificationMode.isCertificateVerificationEnabled() == false) {
            return TrustEverythingConfig.TRUST_EVERYTHING;
        }
        if (certificateAuthorities != null) {
            return new PemTrustConfig(certificateAuthorities, basePath);
        }
        if (trustStorePath != null) {
            final char[] password = resolvePasswordSetting(TRUSTSTORE_SECURE_PASSWORD, TRUSTSTORE_LEGACY_PASSWORD);
            final String storeType = resolveSetting(TRUSTSTORE_TYPE, Function.identity(), inferKeyStoreType(trustStorePath));
            final String algorithm = resolveSetting(TRUSTSTORE_ALGORITHM, Function.identity(), TrustManagerFactory.getDefaultAlgorithm());
            return new StoreTrustConfig(trustStorePath, password, storeType, algorithm, true, basePath);
        }
        return buildDefaultTrustConfig(defaultTrustConfig, keyConfig);
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Choose one trust source: keep either certificate_authorities (PEM) or truststore.path (JKS/PKCS12), remove the other.
  2. If you need both sets of CAs, merge them into a single truststore (keytool -importcert) or a single PEM bundle.
  3. Run a config audit per ssl.* prefix to ensure only one trust style is declared.

Example fix

# before
xpack.security.http.ssl.certificate_authorities: [ "ca.pem" ]
xpack.security.http.ssl.truststore.path: "trust.jks"
# after (pick one)
xpack.security.http.ssl.truststore.path: "trust.jks"
#   (and remove the certificate_authorities line)
Defensive patterns

Strategy: validation

Validate before calling

void checkTrustConfig(Map<String,String> settings, String prefix) {
    boolean hasCa = settings.containsKey(prefix + "certificate_authorities");
    boolean hasTs = settings.containsKey(prefix + "truststore.path");
    if (hasCa && hasTs)
        throw new IllegalArgumentException("Specify either " + prefix + "certificate_authorities OR " + prefix + "truststore.path, not both");
}

Prevention

When it happens

Trigger: Both ssl.certificate_authorities and ssl.truststore.path are set under the same prefix (http.ssl., transport.ssl., etc.). Triggered during load, before any file is read.

Common situations: Migration from PEM to PKCS12 truststore where the old PEM CA entry was left in the config; copy-paste of an example that included both; environment overlay that adds a truststore on top of a PEM-based base config.

Related errors


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