keycloak/keycloak · error · RuntimeException
Failed to load truststore
Error message
Failed to load truststore
What it means
Thrown from HttpClientBuilder.build(AdapterHttpClientConfig) when adapterConfig.getTruststore() is set but KeystoreUtil.loadKeyStore(truststorePath, truststorePassword) throws — file missing, wrong type, wrong password, or unreadable. The path is first run through EnvUtil.replace (so ${env} placeholders are expanded). It becomes a RuntimeException("Failed to load truststore", e) with the cause.
Source
Thrown at adapters/saml/core/src/main/java/org/keycloak/adapters/cloned/HttpClientBuilder.java:349
}
return client;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public HttpClient build(AdapterHttpClientConfig adapterConfig) {
disableCookieCache(); // disable cookie cache as we don't want sticky sessions for load balancing
String truststorePath = adapterConfig.getTruststore();
if (truststorePath != null) {
truststorePath = EnvUtil.replace(truststorePath);
String truststorePassword = adapterConfig.getTruststorePassword();
try {
this.truststore = KeystoreUtil.loadKeyStore(truststorePath, truststorePassword);
} catch (Exception e) {
throw new RuntimeException("Failed to load truststore", e);
}
}
String clientKeystore = adapterConfig.getClientKeystore();
if (clientKeystore != null) {
clientKeystore = EnvUtil.replace(clientKeystore);
String clientKeystorePassword = adapterConfig.getClientKeystorePassword();
try {
KeyStore clientCertKeystore = KeystoreUtil.loadKeyStore(clientKeystore, clientKeystorePassword);
keyStore(clientCertKeystore, clientKeystorePassword);
} catch (Exception e) {
throw new RuntimeException("Failed to load keystore", e);
}
}
HttpClientBuilder.HostnameVerificationPolicy policy = HttpClientBuilder.HostnameVerificationPolicy.WILDCARD;
if (adapterConfig.isAllowAnyHostname())
policy = HttpClientBuilder.HostnameVerificationPolicy.ANY;
connectionPoolSize(adapterConfig.getConnectionPoolSize());View on GitHub (pinned to 66c7e15a37)
Solutions
- Inspect RuntimeException.getCause() for the precise keystore error (FileNotFoundException vs IOException vs CertificateException).
- Confirm the absolute path the adapter sees after EnvUtil.replace (resolve ${env} vars and expand relative paths).
- Verify the password matches and the file is the expected keystore type.
- Ensure the file is readable by the adapter process/container user.
Example fix
<!-- before: path missing / wrong password -->
<truststore>file:${jboss.server.config.dir}/trust.jks</truststore>
<truststorePassword>old-password</truststorePassword>
<!-- after: absolute path exists and password is correct -->
<truststore>/opt/keycloak/conf/trust.jks</truststore>
<truststorePassword>correct-password</truststorePassword> Defensive patterns
Strategy: validation
Validate before calling
String path = EnvUtil.replace(adapterConfig.getTruststore());
File f = new File(path);
if (adapterConfig.getTruststore() != null && (!f.isFile() || !f.canRead())) {
throw new IllegalStateException("Truststore not readable: " + f.getAbsolutePath());
}
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
try (InputStream is = new FileInputStream(f)) {
ks.load(is, adapterConfig.getTruststorePassword().toCharArray()); // throws on wrong password
} Try / catch
try {
HttpClient client = new HttpClientBuilder().build(adapterConfig);
} catch (RuntimeException e) {
if (e.getMessage().equals("Failed to load truststore")) logger.error("Bad truststore config", e.getCause());
throw e;
} Prevention
- Use absolute paths (or ${env} vars that are guaranteed set) for keystore references.
- Load the truststore in a startup self-check so misconfiguration fails at boot, not at first request.
- Keep the keystore type explicit to avoid JKS/PKCS12 ambiguity.
When it happens
Trigger: Configuring <truststore>/<truststorePassword> (or equivalent AdapterHttpClientConfig) where the file path resolves (after env substitution) to a missing/unreadable file, the type is unsupported, or the password is wrong.
Common situations: Relative path resolved against an unexpected working directory; ${env} variable not set so the literal placeholder is used; truststore password mismatch; truststore in PKCS12 but expected JKS (or vice-versa); file permission issue in a container.
Related errors
- Failed to load keystore
- KeyStore {key.getKeystore().getFile()} does not exist
- KeyStore {key.getKeystore().getResource()} does not exist
- KeyStore element must have the url or classpath attribute se
- Hostname verification failure
AI-assisted analysis of keycloak/keycloak@66c7e15a37 (2026-08-14).
Data as JSON: /api/errors/7e8450df6b0b0328.
Report an issue: GitHub.