elastic/elasticsearch · error · CertificateException
This trust manager is for client use only and cannot trust…
Error message
This trust manager is for client use only and cannot trust other clients
What it means
Thrown by the same custom X509TrustManager's `checkClientTrusted` override. The trust manager built by `buildTrustManagerFromLeafCertificates` is purpose-built for CLIENT-side verification of a SERVER (leaf-pinning); it explicitly refuses to act as a server-side trust manager that validates inbound client certs. Calling `checkClientTrusted` is a misuse of this manager.
Solutions
- Use CA-based or trustStore-based trust (`certificateAuthorities` / `trustStoreFile`) instead of `serverCertificate` when client-cert verification is needed — those build standard `X509TrustManager`s that support both directions.
- If you only need server verification, ensure no code path triggers client-cert checking (don't install this manager on a server socket).
- Re-architect the test to use the testclusters framework's built-in SSL setup rather than a hand-rolled context.
Example fix
// before: leaf mode cannot do mTLS
testClusters.c.serverCertificate = file('leaf.pem')
// after: CA mode supports both directions
testClusters.c.certificateAuthorities = [file('ca.pem')] Defensive patterns
Strategy: validation
Validate before calling
// Detect leaf-pinning mode and refuse server-side mTLS use
if (serverCertificate != null && needsClientCertValidation) {
throw new IllegalStateException("Leaf-pin trust manager cannot validate client certs; use CA mode.");
} Prevention
- Reserve `serverCertificate` (leaf pinning) for client-to-server verification only.
- For mutual TLS, always configure `certificateAuthorities` or `trustStoreFile`.
- Document the directional limitation of leaf-pin trust in the SSL setup helper.
When it happens
Trigger: This trust manager (built from `serverCertificate` leaf config) is installed into a context performing server-side client-cert verification (mutual TLS where ES acts as server validating client certs). The resolver's leaf mode only supports one direction.
Common situations: A test inadvertently uses leaf-pinning trust config in a context that needs bidirectional TLS; wiring the test client's trust manager into a server socket factory; custom networking code that calls `sslContext.init(..., trustManager, ...)` and then the runtime invokes `checkClientTrusted` during an mTLS handshake.
Related errors
- Cannot specify more than one trust method
- Trust-store does not contain any trusted certificate entries
- Untrusted leaf certificate
- Can not use with
- SSL trust has been configured, but
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/6de4981cf8829a03.
Report an issue: GitHub.
Appendix: source
Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/SslTrustResolver.java:177
var trustManager = new X509TrustManager() {
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
final X509Certificate leaf = chain[0];
if (trusted.contains(leaf) == false) {
throw new CertificateException("Untrusted leaf certificate: " + leaf.getSubjectX500Principal());
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
// This doesn't apply when trusting leaf certs, and is only really needed for server trust managers anyways
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
throw new CertificateException("This trust manager is for client use only and cannot trust other clients");
}
};
return new TrustManager[] { trustManager };
}
private static Collection<Certificate> readCertificatesFromKeystore(File file, String password) throws GeneralSecurityException,
IOException {
var keyStore = readKeyStoreFromFile(file, password);
final Set<Certificate> certificates = new HashSet<>(keyStore.size());
var enumeration = keyStore.aliases();
while (enumeration.hasMoreElements()) {
var alias = enumeration.nextElement();
if (keyStore.isKeyEntry(alias)) {
certificates.add(keyStore.getCertificate(alias));
}
}
return certificates;View on GitHub (pinned to db6a809a66)