PKIX path building failed (Java) — truststore fix
PKIX path building failed: Java can't chain the cert to a root in its cacerts store. Import the missing CA or fix the server. Free instant check, no sign-up.
Check your domain for this issue now
Free, no sign-up. Runs the exact check this guide describes and shows what to fix.
Problem
A Java client throws javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target. Java received the server’s certificate and tried to build a chain from it up to a root it trusts — and couldn’t. The missing piece is in Java’s own trust store (cacerts), which is separate from the operating system’s. Either the server didn’t send an intermediate that Java would need to complete the chain, or the root/intermediate simply isn’t in the cacerts this particular JVM is using, or a proxy re-signed the connection with a private CA that cacerts has never heard of. The certificate is rarely broken; the trust anchor is missing.
Symptoms
- The stack trace names
SunCertPathBuilderExceptionand ends withunable to find valid certification path to requested target. Upstream it usually appears asSSLHandshakeExceptionand, one level down,sun.security.validator.ValidatorException. - The same host loads fine in a browser and with
curlon the same machine, but every Java process — a build downloading dependencies, an app calling an API, a JDBC driver over TLS — fails. - It commonly appears right after moving to a new/minimal JDK image, a corporate laptop with a proxy, or an internal service that uses a private CA.
openssl s_client -connect HOST:443 -servername HOSTshows a chain that looks complete to the OS, yet Java still refuses it — the tell that this is a cacerts problem, not a server-down problem.
Top 3 Causes
- The CA isn’t in Java’s cacerts - Java maintains its own trust store and ignores the OS store unless told otherwise. A perfectly public certificate can fail if the JVM is old (its bundled roots predate the CA), stripped down, or simply a different runtime than the one your browser and curl trust. This is the default explanation when “everything else works but Java doesn’t.”
- The server is missing its intermediate certificate - The server sends only the leaf and omits the intermediate that links it to a root. Browsers often fetch the missing intermediate automatically; Java does not do AIA fetching by default, so it can’t build the chain. Here the real bug is on the server (deploy the full chain), and importing the intermediate into cacerts is only a local workaround for one machine.
- A proxy or antivirus is intercepting TLS - A corporate proxy or “HTTPS scanning” antivirus decrypts the connection and re-signs it with a private CA. The OS and browser trust that CA because IT installed it there; Java’s cacerts doesn’t have it, so every Java TLS call fails with PKIX path building failed. The fix is to add that proxy root to the truststore Java uses — after confirming the interception is legitimate.
Diagnose with DechoNet
- SSL Check shows the chain the server actually sends. If the intermediate is missing here, that’s cause #2 and the fix belongs on the server. If the chain is complete from the public internet but Java still fails on your machine, the anchor is missing locally — the CA just isn’t in this JVM’s cacerts (cause #1), or a proxy is re-signing your traffic with a root cacerts doesn’t hold (cause #3).
- HTTP Check confirms the endpoint responds once TLS is set aside, so you can separate a trust-store problem from an unreachable service.
Resolution Checklist
- Find the JVM in play first:
which java,java -version, and the process’sJAVA_HOME. The cacerts you fix must belong to the JDK/JRE that actually launches your app, or nothing changes. - Inspect the served chain:
openssl s_client -connect YOUR_DOMAIN:443 -servername YOUR_DOMAIN -showcerts. OneCERTIFICATEblock with no intermediate → cause #2; fix the server by deploying the full chain and re-run SSL Check to confirm. - If the server chain is complete but Java still fails, import the missing CA into cacerts:
keytool -importcert -trustcacerts -alias your-ca -file ca.crt -keystore "$JAVA_HOME/lib/security/cacerts" -storepass changeit. Prefer importing the intermediate/root CA, not the leaf — the leaf changes on every renewal, the CA doesn’t. - Prefer a dedicated truststore over editing the JDK’s cacerts in place (JDK upgrades replace cacerts and silently drop your import). Point the app at it with
-Djavax.net.ssl.trustStore=/path/store.jks -Djavax.net.ssl.trustStorePassword=.... - Turn on handshake logging to see exactly where the chain breaks:
-Djavax.net.debug=ssl:handshake. Atlassian’s smallSSLPokeclass is a quick way to test a single host against the current truststore without your whole app. - For a legitimate corporate proxy, import its root into the truststore Java uses — the same way, with keytool. If you can’t identify the intercepting CA, don’t import it; verify it’s really your IT department’s proxy first.
When to Escalate
- If SSL Check shows a complete chain from the internet but Java fails only on certain machines, those JVMs are missing the CA or sitting behind a proxy whose root was never distributed to Java. That’s a fleet/IT task — roll the CA into the base image or the managed truststore, not into one developer’s laptop.
- Never reach for a trust-all
TrustManageror-Dcom.sun.net.ssl...shortcut to make it disappear. Disabling verification converts a missing-anchor error — which is protecting you — into a silent, permanent hole that behaves identically whether the far end is your real server or an attacker holding a forged certificate.
Related Tools
Related Guides
Share this guide