elastic/elasticsearch · error · IllegalStateException

Cannot specify more than one trust method (CA=%s, trustStore

Error message

Cannot specify more than one trust method (CA=%s, trustStore=%s, serverCert=%s, serverKeyStore=%s)

What it means

SslTrustResolver.buildTrustManagers() counts how many of four trust inputs are non-null — `certificateAuthorities`, `trustStoreFile`, `serverCertificate`, `serverKeyStoreFile` — and refuses if more than one is set. The resolver can only build a single coherent trust strategy, so multiple inputs are ambiguous; exactly one must be chosen or none (null returns `null` trust managers, meaning use the JVM default).

Source

Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/SslTrustResolver.java:92

        final TrustManager[] trustManagers = buildTrustManagers();
        if (trustManagers != null) {
            return createSslContext(trustManagers);
        } else {
            return null;
        }
    }

    TrustManager[] buildTrustManagers() throws GeneralSecurityException, IOException {
        var configurationCount = Stream.of(
            this.certificateAuthorities,
            this.trustStoreFile,
            this.serverCertificate,
            this.serverKeyStoreFile
        ).filter(Objects::nonNull).count();
        if (configurationCount == 0) {
            return null;
        } else if (configurationCount > 1) {
            throw new IllegalStateException(
                String.format(
                    Locale.ROOT,
                    "Cannot specify more than one trust method (CA=%s, trustStore=%s, serverCert=%s, serverKeyStore=%s)",
                    certificateAuthorities,
                    trustStoreFile,
                    serverCertificate,
                    serverKeyStoreFile
                )
            );
        }
        if (this.certificateAuthorities != null) {
            return getTrustManagers(buildTrustStoreFromCA(certificateAuthorities));
        } else if (this.trustStoreFile != null) {
            return getTrustManagers(readKeyStoreFromFile(trustStoreFile, trustStorePassword));
        } else if (this.serverCertificate != null) {
            return buildTrustManagerFromLeafCertificates(head(readCertificates(serverCertificate)));
        } else if (this.serverKeyStoreFile != null) {
            return buildTrustManagerFromLeafCertificates(readCertificatesFromKeystore(serverKeyStoreFile, serverKeyStorePassword));

View on GitHub (pinned to db6a809a66)

Solutions

  1. Inspect the cluster's SSL config and keep exactly ONE trust source: CA, trustStore, serverCert, or serverKeyStore.
  2. If you need a fresh start, null-out the previously set field before assigning the new one (the resolver reads raw fields, not a builder).
  3. The message prints all four field values — the non-null ones are the offenders to clear.

Example fix

// before
testClusters.c.setting('...ca...', '/path/ca.pem')
// and somewhere
certificateAuthorities = [file('ca.pem')]
trustStoreFile = file('trust.jks')
// after
// keep only one:
certificateAuthorities = [file('ca.pem')]
// trustStoreFile = null
Defensive patterns

Strategy: validation

Validate before calling

long configured = Stream.of(ca, trustStoreFile, serverCert, serverKeyStoreFile)
    .filter(Objects::nonNull).count();
if (configured > 1) {
  throw new IllegalStateException("Pick exactly one SSL trust source; got " + configured);
}

Prevention

When it happens

Trigger: Configuring a test cluster's SSL with two or more of: a CA file, a trustStore file, a leaf server certificate, and a server keyStore file — via the DSL's `.certificateAuthorities(...)`, `.trustStoreFile(...)`, `.serverCertificate(...)`, or `.serverKeyStoreFile(...)` setters.

Common situations: A test initially set up with a CA later gets a `.trustStoreFile` added for a different test scenario without clearing the CA; copy-pasting SSL setup from two examples; migrating from trustStore-based to CA-based trust but leaving the old field populated.

Related errors


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