{"record":{"id":"b40f3c5c7ff33948","repo":"elastic/elasticsearch","slug":"cannot-specify-more-than-one-trust-method-ca-s","errorCode":null,"errorMessage":"Cannot specify more than one trust method (CA=%s, trustStore=%s, serverCert=%s, serverKeyStore=%s)","messagePattern":"Cannot specify more than one trust method \\(CA=(.+?), trustStore=(.+?), serverCert=(.+?), serverKeyStore=(.+?)\\)","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"build-tools/src/main/java/org/elasticsearch/gradle/testclusters/SslTrustResolver.java","lineNumber":92,"sourceCode":"        final TrustManager[] trustManagers = buildTrustManagers();\n        if (trustManagers != null) {\n            return createSslContext(trustManagers);\n        } else {\n            return null;\n        }\n    }\n\n    TrustManager[] buildTrustManagers() throws GeneralSecurityException, IOException {\n        var configurationCount = Stream.of(\n            this.certificateAuthorities,\n            this.trustStoreFile,\n            this.serverCertificate,\n            this.serverKeyStoreFile\n        ).filter(Objects::nonNull).count();\n        if (configurationCount == 0) {\n            return null;\n        } else if (configurationCount > 1) {\n            throw new IllegalStateException(\n                String.format(\n                    Locale.ROOT,\n                    \"Cannot specify more than one trust method (CA=%s, trustStore=%s, serverCert=%s, serverKeyStore=%s)\",\n                    certificateAuthorities,\n                    trustStoreFile,\n                    serverCertificate,\n                    serverKeyStoreFile\n                )\n            );\n        }\n        if (this.certificateAuthorities != null) {\n            return getTrustManagers(buildTrustStoreFromCA(certificateAuthorities));\n        } else if (this.trustStoreFile != null) {\n            return getTrustManagers(readKeyStoreFromFile(trustStoreFile, trustStorePassword));\n        } else if (this.serverCertificate != null) {\n            return buildTrustManagerFromLeafCertificates(head(readCertificates(serverCertificate)));\n        } else if (this.serverKeyStoreFile != null) {\n            return buildTrustManagerFromLeafCertificates(readCertificatesFromKeystore(serverKeyStoreFile, serverKeyStorePassword));","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/SslTrustResolver.java#L74-L110","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the cluster's SSL config and keep exactly ONE trust source: CA, trustStore, serverCert, or serverKeyStore.","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).","The message prints all four field values — the non-null ones are the offenders to clear."],"exampleFix":"// before\ntestClusters.c.setting('...ca...', '/path/ca.pem')\n// and somewhere\ncertificateAuthorities = [file('ca.pem')]\ntrustStoreFile = file('trust.jks')\n// after\n// keep only one:\ncertificateAuthorities = [file('ca.pem')]\n// trustStoreFile = null","handlingStrategy":"validation","validationCode":"long configured = Stream.of(ca, trustStoreFile, serverCert, serverKeyStoreFile)\n    .filter(Objects::nonNull).count();\nif (configured > 1) {\n  throw new IllegalStateException(\"Pick exactly one SSL trust source; got \" + configured);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Centralize SSL setup in one convention method that takes a single 'mode' parameter.","When migrating trust modes, explicitly null the old field before setting the new one.","Add a build sanity-check that counts non-null SSL inputs and fails fast in configuration."],"tags":["gradle","testclusters","ssl","tls","configuration","build-tools"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}