apache/beam · error · IOException
Can't load the client certificate from the keystore
Error message
Can't load the client certificate from the keystore
What it means
ConnectionConfiguration.getSSLContext() builds an SSLContext from a provided keystore to secure TLS connections to Elasticsearch. Any exception while loading the keystore file or the trust material (bad password, corrupt/malformed file, unreadable path) is rethrown as an IOException with this message, wrapping the underlying cause.
Solutions
- Check the wrapped cause in the exception for the exact keystore failure reason
- Verify keystorePath points to an existing, readable keystore file
- Confirm keystorePassword matches the keystore's actual password
- Validate the keystore with `keytool -list -keystore <path>` before deploying
- Ensure the keystore format matches KeyStore.getDefaultType() (JKS vs PKCS12)
Example fix
// before
ConnectionConfiguration.create("es-host", 9200)
.setKeystorePath("/secrets/keystore.jks").setKeystorePassword(null);
// after
ConnectionConfiguration.create("es-host", 9200)
.setKeystorePath("/secrets/keystore.jks").setKeystorePassword(keystorePassword); Defensive patterns
Strategy: validation
Validate before calling
File ks = new File(keystorePath);
if (!ks.isFile() || !ks.canRead())
throw new IllegalArgumentException("Keystore missing/unreadable: " + keystorePath);
try (InputStream in = new FileInputStream(ks)) {
KeyStore.getInstance("PKCS12").load(in, password.toCharArray()); // throws if bad
} Try / catch
try {
pipeline.apply(ElasticsearchIO.read().withConnectionConfiguration(cc));
} catch (IllegalArgumentException | IOException e) {
throw new IllegalStateException("ES TLS setup failed: " + e.getCause(), e);
} Prevention
- Run keytool -list against the keystore in CI before deploying
- Store keystore passwords in a secret manager, not config files
- Pin the keystore format explicitly (JKS vs PKCS12)
When it happens
Trigger: ConnectionConfiguration.setKeystorePath(...)/setKeystorePassword(...) set to a nonexistent, corrupt, or password-protected keystore; wrong keystore password; keystore bytes not loadable as a KeyStore.
Common situations: Typo in keystore path in deployment config; keystore regenerated with a different password; secret mounted empty in Kubernetes; JKS vs PKCS12 format mismatch.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Both clientCertPath and clientCertKeyPath must be specified…
- Cannot get Elasticsearch version
- Error writing to ES after
- <errorMessages.toString()>
- private key cannot be null
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/dc173899c3d1647b.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/elasticsearch/src/main/java/org/apache/beam/sdk/io/elasticsearch/ElasticsearchIO.java:708
builder.addIfNotNull(DisplayData.item("socketTimeout", getSocketTimeout()));
builder.addIfNotNull(DisplayData.item("connectTimeout", getConnectTimeout()));
builder.addIfNotNull(DisplayData.item("trustSelfSignedCerts", isTrustSelfSignedCerts()));
builder.addIfNotNull(DisplayData.item("compressionEnabled", isCompressionEnabled()));
}
private SSLContext getSSLContext() throws IOException {
if (getKeystorePath() != null && !getKeystorePath().isEmpty()) {
try {
KeyStore keyStore = KeyStore.getInstance("jks");
try (InputStream is = new FileInputStream(new File(getKeystorePath()))) {
String keystorePassword = getKeystorePassword();
keyStore.load(is, (keystorePassword == null) ? null : keystorePassword.toCharArray());
}
final TrustStrategy trustStrategy =
isTrustSelfSignedCerts() ? new TrustSelfSignedStrategy() : null;
return SSLContexts.custom().loadTrustMaterial(keyStore, trustStrategy).build();
} catch (Exception e) {
throw new IOException("Can't load the client certificate from the keystore", e);
}
}
return null;
}
@VisibleForTesting
RestClient createClient() throws IOException {
HttpHost[] hosts = new HttpHost[getAddresses().size()];
int i = 0;
for (String address : getAddresses()) {
URL url = new URL(address);
hosts[i] = new HttpHost(url.getHost(), url.getPort(), url.getProtocol());
i++;
}
RestClientBuilder restClientBuilder = RestClient.builder(hosts);
if (getPathPrefix() != null) {
restClientBuilder.setPathPrefix(getPathPrefix());
}View on GitHub (pinned to 12126d8942)