# sun.security.validator.ValidatorException: PKIX path building failed

## TL;DR
The JVM cannot build a trust chain for the server's certificate because the issuing CA is not in the JVM's own truststore (cacerts), which is separate from the OS trust store. Import the missing CA certificate into the cacerts file your JVM actually uses with keytool, restart the JVM, and the HTTPS calls succeed. Installing the CA at the OS level does nothing for Java.

```text
sun.security.validator.ValidatorException: PKIX path building failed
```

## Use this when
- A Java service fails calling an HTTPS endpoint that browsers open fine
- It broke after a corporate proxy CA change or a new internal CA
- The full message mentions "unable to find valid certification path to requested target"
- Spring Boot, Tomcat, or a batch job throws ValidatorException on startup or first call

## Not for this skill when
- The certificate is expired (fix the cert, not the truststore)
- Hostname verification fails (the chain is fine; the name is wrong)
- The client and server cannot agree on a TLS version

## Steps
1. Confirm the chain problem independently of Java:
   ```bash
   echo | openssl s_client -connect example.com:443 -servername example.com
   ```
   Check the verify return code. If openssl is happy, the server chain is fine and this is purely a JVM truststore gap.
   Expected: you know the server is serving a complete chain, so the fix belongs in the JVM.

2. Find which cacerts your JVM actually uses. Containers and servers often have several JREs; the running one may not be the one on your PATH. Check JAVA_HOME of the running process and look for its lib/security/cacerts file.
   Expected: the exact cacerts path the failing JVM reads at startup.

3. Import the CA certificate:
   ```bash
   keytool -importcert -alias [descriptive name] -file [ca cert file]      -keystore [path to cacerts] -storepass [the store password]
   ```
   Answer yes to the trust prompt. Use a descriptive alias so the next person knows what it is and why it is there.
   Expected: keytool reports the certificate was added to the keystore.

4. Restart the JVM and retest. The truststore is read once at startup, so a running process never picks up the change without a restart. Then verify the previously failing HTTPS call works.
   Expected: no more ValidatorException, and the call succeeds.

### Variant: "unable to find valid certification path to requested target"
The wrapped message most people actually see in logs. Same cause, same fix. Search for this phrasing when the ValidatorException class name is buried.

### Variant: corporate proxy CA
The proxy intercepts TLS with its own CA, which no default truststore knows. Every JVM behind the proxy needs the proxy CA imported. If new services keep hitting this, bake the CA into your base container image instead of fixing hosts one by one.

### Variant: Spring Boot in Docker
The container's JRE has its own cacerts, independent of the build machine and the host. Import during the image build so every container starts with the CA present. A read-only filesystem at runtime makes after-the-fact imports impossible.

### Variant: self-signed internal service certs
Importing the internal CA (which signed the service cert) is cleaner than importing each service cert. One import covers every current and future cert from that CA.

## Why this happens
Java does not use the operating system's certificate store. Each JVM ships with its own cacerts file of trusted roots. OS-level CA installs, browser trust, and curl's bundle are all invisible to Java, so a chain that validates everywhere else fails in the JVM until its own store learns the CA.

## Edge cases and pitfalls
- Importing into the wrong cacerts (another JRE on the same box) is the most common reason "the fix didn't work." Verify with the running process's JAVA_HOME.
- Never "fix" this with a trust-all X509TrustManager. That disables verification for every connection the JVM makes, which is far worse than the original error.
- Keytool alias collisions silently replace entries. Use unique, descriptive aliases.
- Document why the CA was added. An unexplained CA in cacerts is a future incident: nobody knows if it is still needed or still trustworthy.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_vm7gbRT7fcLxsz4lVWB7ow
