{"record":{"id":"7e8450df6b0b0328","repo":"keycloak/keycloak","slug":"failed-to-load-truststore","errorCode":null,"errorMessage":"Failed to load truststore","messagePattern":"Failed to load truststore","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"adapters/saml/core/src/main/java/org/keycloak/adapters/cloned/HttpClientBuilder.java","lineNumber":349,"sourceCode":"\n            }\n            return client;\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public HttpClient build(AdapterHttpClientConfig adapterConfig) {\n        disableCookieCache(); // disable cookie cache as we don't want sticky sessions for load balancing\n\n        String truststorePath = adapterConfig.getTruststore();\n        if (truststorePath != null) {\n            truststorePath = EnvUtil.replace(truststorePath);\n            String truststorePassword = adapterConfig.getTruststorePassword();\n            try {\n                this.truststore = KeystoreUtil.loadKeyStore(truststorePath, truststorePassword);\n            } catch (Exception e) {\n                throw new RuntimeException(\"Failed to load truststore\", e);\n            }\n        }\n        String clientKeystore = adapterConfig.getClientKeystore();\n        if (clientKeystore != null) {\n            clientKeystore = EnvUtil.replace(clientKeystore);\n            String clientKeystorePassword = adapterConfig.getClientKeystorePassword();\n            try {\n                KeyStore clientCertKeystore = KeystoreUtil.loadKeyStore(clientKeystore, clientKeystorePassword);\n                keyStore(clientCertKeystore, clientKeystorePassword);\n            } catch (Exception e) {\n                throw new RuntimeException(\"Failed to load keystore\", e);\n            }\n        }\n\n        HttpClientBuilder.HostnameVerificationPolicy policy = HttpClientBuilder.HostnameVerificationPolicy.WILDCARD;\n        if (adapterConfig.isAllowAnyHostname())\n            policy = HttpClientBuilder.HostnameVerificationPolicy.ANY;\n        connectionPoolSize(adapterConfig.getConnectionPoolSize());","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/keycloak/keycloak/blob/66c7e15a3788de7764f07dd2558275a02770e16d/adapters/saml/core/src/main/java/org/keycloak/adapters/cloned/HttpClientBuilder.java#L331-L367","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"<!-- before: path missing / wrong password -->\n<truststore>file:${jboss.server.config.dir}/trust.jks</truststore>\n<truststorePassword>old-password</truststorePassword>\n<!-- after: absolute path exists and password is correct -->\n<truststore>/opt/keycloak/conf/trust.jks</truststore>\n<truststorePassword>correct-password</truststorePassword>","handlingStrategy":"validation","validationCode":"String path = EnvUtil.replace(adapterConfig.getTruststore());\nFile f = new File(path);\nif (adapterConfig.getTruststore() != null && (!f.isFile() || !f.canRead())) {\n    throw new IllegalStateException(\"Truststore not readable: \" + f.getAbsolutePath());\n}\nKeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());\ntry (InputStream is = new FileInputStream(f)) {\n    ks.load(is, adapterConfig.getTruststorePassword().toCharArray()); // throws on wrong password\n}","typeGuard":null,"tryCatchPattern":"try {\n    HttpClient client = new HttpClientBuilder().build(adapterConfig);\n} catch (RuntimeException e) {\n    if (e.getMessage().equals(\"Failed to load truststore\")) logger.error(\"Bad truststore config\", e.getCause());\n    throw e;\n}","preventionTips":["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."],"tags":["ssl","truststore","keystore","configuration","keycloak-adapter"],"backgroundTag":null,"analyzedSha":"66c7e15a3788de7764f07dd2558275a02770e16d","analyzedAt":"2026-08-14T01:36:42.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}