Introduction

The PKIX path building failed error occurs when Java's SSL implementation cannot build a trusted certificate chain to the server's certificate. Unlike some HTTP clients, Java requires the full chain to be trusted in its keystore, and self-signed or corporate CA-signed certificates are not trusted by default.

This is a common issue when connecting to internal services, using self-signed certificates, or working behind corporate TLS proxies.

Symptoms

  • HTTPS connection fails with "javax.net.ssl.SSLHandshakeException: PKIX path building failed"
  • Caused by: "sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path"
  • Same URL works in browser but Java code throws SSL exception

Common Causes

  • Server certificate is signed by a CA not in Java's default truststore
  • Self-signed certificate is used on the target server
  • Corporate TLS intercepting proxy re-signs certificates with an internal CA

Step-by-Step Fix

  1. 1.Import the certificate into Java truststore: Add the server's CA certificate to cacerts.
  2. 2.```bash
  3. 3.# Download the server certificate:
  4. 4.echo | openssl s_client -connect api.example.com:443 -showcerts 2>/dev/null | \
  5. 5.openssl x509 -out server.crt

# Import into Java truststore: sudo keytool -importcert \ -alias api-example-com \ -file server.crt \ -keystore $JAVA_HOME/lib/security/cacerts \ -storepass changeit \ -noprompt ```

  1. 1.Use a custom truststore for the application: Don't modify the global cacerts.
  2. 2.```bash
  3. 3.# Create a custom truststore:
  4. 4.keytool -importcert \
  5. 5.-alias my-ca \
  6. 6.-file corporate-ca.crt \
  7. 7.-keystore app-truststore.jks \
  8. 8.-storepass mypassword \
  9. 9.-noprompt

# Use it at runtime: java -Djavax.net.ssl.trustStore=/path/to/app-truststore.jks \ -Djavax.net.ssl.trustStorePassword=mypassword \ -jar myapp.jar ```

  1. 1.Configure truststore in Spring Boot: Set truststore properties in application.yml.
  2. 2.```yaml
  3. 3.# application.yml:
  4. 4.server:
  5. 5.ssl:
  6. 6.trust-store: classpath:truststore.jks
  7. 7.trust-store-password: ${TRUSTSTORE_PASSWORD}
  8. 8.trust-store-type: JKS
  9. 9.`
  10. 10.Debug SSL handshake to identify the issue: Enable SSL debugging to see exactly what fails.
  11. 11.```bash
  12. 12.# Enable SSL debugging:
  13. 13.java -Djavax.net.debug=ssl:handshake -jar app.jar

# Output shows the certificate chain: # *** Certificate chain # chain [0] = [ # Subject: CN=api.example.com # Issuer: CN=Corporate Internal CA # ] ```

Prevention

  • Use proper CA-signed certificates from trusted authorities (Let's Encrypt, etc.)
  • Maintain application-specific truststores instead of modifying the global cacerts
  • Include truststore setup in infrastructure provisioning scripts
  • Enable SSL debugging in staging environments to catch trust issues early