“PKIX path building failed”: how to fix the Java error

The error means Java could not build a chain from the server certificate to a root CA it trusts. The cause lies either on the server or in your Java application’s truststore.

The error message

javax.net.ssl.SSLHandshakeException: PKIX path building failed:
  sun.security.provider.certpath.SunCertPathBuilderException:
  unable to find valid certification path to requested target

PKIX is the method Java uses to validate certificate chains. Java takes the server’s certificate and follows the issuers to build an unbroken chain up to a root CA in the truststore. If it cannot, the connection is aborted. That happens with HTTP clients, JDBC drivers, LDAP, Maven, Gradle and Jenkins alike.

The most common causes

  1. The server does not send an intermediate certificate. Browsers often compensate by downloading missing certificates. Java does not do that by default. That is why it works in the browser but not in Java.
  2. An internal or company CA. The server uses a certificate from its own CA that is not in Java’s truststore.
  3. A proxy intercepts TLS. Corporate proxies such as Zscaler or Netskope replace the certificate with their own. Java does not know their root; the browser does, because IT distributed it to the operating system.
  4. A custom truststore replaces cacerts. With -Djavax.net.ssl.trustStore=… Java uses only that file. If the public roots are missing there, every other connection fails.
  5. An old JDK. Very old Java versions do not know newer roots.

Find the cause

Check the server first. The SSL check shows which certificates the server delivers and whether the chain is complete. On the command line:

openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null

If there is only one certificate (depth=0) and its issuer is an intermediate CA, the chain is missing. Next, check which truststore Java really uses:

java -Djavax.net.debug=ssl:trustmanager -jar app.jar 2>&1 | grep -i "truststore"

The output names the file, for example trustStore is: /usr/lib/jvm/java-21/lib/security/cacerts. With -Djavax.net.debug=ssl:handshake you also see which certificates the server sent.

Fix 1: repair the chain on the server

If the intermediate certificate is missing, it belongs on the server. That is the only fix that helps all clients at once. In nginx the intermediate goes into the same file after the server certificate (fullchain.pem), likewise in Apache’s SSLCertificateFile. The certificate converter adds missing intermediates automatically.

Fix 2: add the CA to the truststore

With internal CAs or a TLS proxy you have to make the root CA known to Java. Use the root or intermediate CA, not the server certificate itself, or it breaks again at the next certificate change.

# Java 9 and later: straight into the running JDK's cacerts
keytool -importcert -cacerts -alias company-root -file company-root.crt -storepass changeit -noprompt

# a separate truststore for one application
keytool -importcert -keystore truststore.p12 -storetype PKCS12 -alias company-root -file company-root.crt
java -Djavax.net.ssl.trustStore=truststore.p12 -Djavax.net.ssl.trustStorePassword=secret -jar app.jar

Careful with a separate truststore: it replaces cacerts completely. If the application also needs to reach public servers, copy cacerts first and add the CA there. More in the article import a certificate into cacerts.

Without keytool, do it in the browser: in the SSL check click “Add to Java truststore”. The chain opens in the Java keystore helper, where you pick the CA and save the truststore as JKS or PKCS#12.

Fix 3: use the system certificate store

If IT has already distributed the company CA to the operating system, Java can use that store directly:

What not to do

Code snippets with a TrustManager that accepts everything, or options like -Dmaven.wagon.http.ssl.insecure=true, circulate online. The connection is then “encrypted”, but anyone on the network can impersonate the server. Acceptable for a quick test at most, never in production.

FAQ

Why does the site work in the browser but not in Java?

Browsers download missing intermediates via the address in the certificate (AIA) and use the system certificate store. Java does neither by default. So usually an intermediate is missing on the server, or the company CA is only in the system store.

Can Java download missing intermediates itself?

Yes, with -Dcom.sun.security.enableAIAcaIssuers=true. It is a workaround: it needs internet access to the CA and slows down the first connection. Better repair the chain on the server.

Do I have to import the CA again after a Java update?

For certificates imported manually into the JDK’s cacerts, often yes, because updates replace the file. On Linux with the system store, or with a separate truststore outside the JDK, that does not happen.

What is the difference to “unable to get local issuer certificate”?

It is the same error from the point of view of OpenSSL, curl or Python. The causes and fixes are the same.