Fix Java “PKIX path building failed”

Check the server chain and the running JVM’s trust configuration before importing a verified private CA.

Best practices
Illustration of encrypted network connections

When SSLHandshakeException contains PKIX path building failed, Java could not build an acceptable certificate path using the trust configuration available to that connection. Common causes include an incomplete server chain, a private CA absent from the trust store, or an application using a different trust store than expected.

Check the server before adding trust

openssl s_client -connect api.example.com:443 \
  -servername api.example.com -showcerts \
  -verify_hostname api.example.com -verify_return_error

Inspect the supplied intermediates and verification result. OpenSSL's trust configuration is not necessarily Java's, so this is supporting evidence, not a substitute for testing the original JVM.

If the server omits an intermediate, correct its certificate chain. A browser may succeed through different roots, cached intermediates, or certificate retrieval behavior. Do not conclude that every browser uses the same operating-system store or that Java can never retrieve intermediates.

Identify the actual JVM and trust manager

Check the executable used by the running process, its javax.net.ssl.trustStore settings, and any application-specific HTTP client configuration. A custom SSLContext can use trust material independently of the JVM defaults.

For the default JSSE implementation, an explicitly configured trust store takes precedence. Otherwise, the runtime searches its default security locations, including jssecacerts before cacerts. Editing another JDK's files will not affect the process that failed.

For a public endpoint, prefer fixing its chain or updating the supported JDK and CA material. For an internal CA, obtain the CA certificate through your organization's trusted PKI channel and verify its fingerprint and intended use:

keytool -printcert -file company-root-ca.pem

A certificate downloaded from the failing connection is not independently verified simply because it can be imported.

Use an application-specific trust store

If the application needs the runtime's existing public roots plus the verified company CA, copy the intended baseline and extend that copy:

umask 077
cp "$JAVA_HOME/lib/security/cacerts" myapp-truststore
keytool -importcert -alias company-root-ca \
  -file company-root-ca.pem -keystore myapp-truststore

Supply the existing store password interactively and confirm the fingerprint. A filename extension does not determine whether the store is JKS or PKCS12. Check its actual format and configure javax.net.ssl.trustStoreType when necessary.

java -Djavax.net.ssl.trustStore=/path/to/myapp-truststore -jar app.jar

Where the application requires a store password, deliver it through controlled launch or secret-management configuration. Keep it out of source control and logs. A copied CA store also needs an update process; it does not inherit future changes to the JDK's original file automatically.

Retest the original caller

Restart or reinitialize the application as required for its SSL context, then retry the same target from the same runtime. If needed, temporarily enable handshake diagnostics:

-Djavax.net.debug=ssl:handshake

Restrict access to diagnostic output and disable it after troubleshooting. Never replace the trust manager with an accept-all implementation or disable hostname verification to suppress the exception.

If tracing is configured, Guance trace details can help correlate the failed call with application logs and latency. An external probe may use a different trust store and cannot establish that the JVM has been fixed.

Reference: JSSE trust management.

Related reading

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting