Sentry Answers>Java>

How to solve the 'PKIX path building failed' error in Java?

How to solve the 'PKIX path building failed' error in Java?

Abdul D.

The Problem

I encounter the PKIX path building failed error when trying to connect to a server using HTTPS:

Click to Copy
import java.io.IOException; import java.net.URL; import javax.net.ssl.HttpsURLConnection; public class Main { public static void main(String[] args) { try { URL url = new URL("https://expired-rsa-ev.ssl.com/"); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); System.out.println("Response Code: " + connection.getResponseCode()); } catch (IOException e) { e.printStackTrace(); } } }

Trying to connect to the URL in the code above throws the following exception:

Click to Copy
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alert.createSSLException(Alert.java:131) at sun.security.ssl.TransportContext.fatal(TransportContext.java:324) at sun.security.ssl.TransportContext.fatal(TransportContext.java:267) at sun.security.ssl.TransportContext.fatal(TransportContext.java:262) at sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1325) at sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1200) at sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1143) at sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392) at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444) at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:422) at sun.security.ssl.TransportContext.dispatch(TransportContext.java:182) at sun.security.ssl.SSLTransport.decode(SSLTransport.java:152) at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1198) at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1107) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:398) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:370) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:567) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:162) at Main.main(Main.java:9)

The Solution

This error occurs when Java cannot verify the SSL certificate of the server you are trying to connect to. This is usually because the certificate isn’t trusted by the Java TrustStore. You can resolve this issue by importing the SSL certificate into the default Java TrustStore or your own custom TrustStore. Alternatively, you can disable SSL certificate validation. This last option is not recommended, as it compromises security.

Importing the Server Certificate into Java TrustStore

The most common solution is to import the server’s SSL certificate into your Java TrustStore.

  1. Open your browser and export the server’s certificate in .cer format.

  2. Use the keytool command to import the certificate into the Java TrustStore:

    Click to Copy
    keytool -import -alias server_cert -file server.cer -keystore cacerts
    • The default location of the cacerts TrustStore is usually JAVA_HOME/lib/security/cacerts.
    • The default password for the TrustStore is changeit.

Specifying a Custom TrustStore

If you don’t want to modify the default TrustStore, you can create a custom TrustStore for your application.

First, create a TrustStore and import the certificate:

Click to Copy
keytool -import -alias server_cert -file server.cer -keystore customTrustStore.jks

Then specify the custom TrustStore when running your Java application:

Click to Copy
java -Djavax.net.ssl.trustStore=customTrustStore.jks -Djavax.net.ssl.trustStorePassword=your_password YourApplication

Disabling Certificate Validation

For development purposes, you can disable SSL certificate validation. However, this is not recommended for production environments as it compromises security.

The following example demonstrates how to disable certificate validation by creating a method to trust all certificates:

Click to Copy
/** * Configures SSL to trust all certificates and bypass hostname verification. * This allows the application to connect to servers with untrusted or self-signed certificates. * WARNING: This approach is insecure for production use. */ private static void configureTrustAllSSL() throws Exception { TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { // Do nothing - trust all clients } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { // Do nothing - trust all servers } } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); }

You can call this method before making the HTTPS connection. This will bypass SSL certificate validation and allow you to connect to servers with untrusted or self-signed certificates.

Click to Copy
public static void main(String[] args) { try { // Configure SSL to trust all certificates configureTrustAllSSL(); // URL of the page with an expired or untrusted certificate URL url = new URL("https://expired-rsa-ev.ssl.com/"); // Replace with your URL String pageContent = fetchContentFromURL(url); // Print out the content of the page System.out.println(pageContent); } catch (Exception e) { e.printStackTrace(); } }

The output will display html page content representing a successful connection:

Click to Copy
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <link rel="icon" href="favicon-32x32.png" sizes="32x32" /> <link rel="icon" href="favicon-192x192.png" sizes="192x192" /> <link rel="apple-touch-icon" href="favicon-180x180.png" /> <title>SSL.com - Test Website</title> </head> <body> <h1>SSL.com - Test Website</h1> <p>This is a test website authenticated by <a href="https://www.ssl.com" target="_blank">SSL.com.</a></p> </body> </html>

Here’s the full example code:

Click to Copy
import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.security.cert.X509Certificate; import javax.net.ssl.*; public class SSLBypassExample { public static void main(String[] args) { try { // Configure SSL to trust all certificates configureTrustAllSSL(); // URL of the page with an expired or untrusted certificate URL url = new URL("https://expired-rsa-ev.ssl.com/"); // Replace with your URL String pageContent = fetchContentFromURL(url); // Print the content of the page System.out.println(pageContent); } catch (Exception e) { e.printStackTrace(); } } /** * Configures SSL to trust all certificates and bypass hostname verification. * This allows the application to connect to servers with untrusted or self-signed certificates. * WARNING: This approach is insecure for production use. */ private static void configureTrustAllSSL() throws Exception { TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { // Do nothing - trust all clients } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { // Do nothing - trust all servers } } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); } /** * Fetches the content from the specified URL as a String. * * @param url The URL to fetch content from. * @return The content of the page as a String. * @throws Exception If an error occurs while reading from the URL. */ private static String fetchContentFromURL(URL url) throws Exception { StringBuilder content = new StringBuilder(); // Open HTTPS connection and read content HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { String inputLine; while ((inputLine = in.readLine()) != null) { content.append(inputLine); } } return content.toString(); } }

Warning: This should only be used in development or testing environments where security is not a concern.

  • Sentry BlogException Handling in Java (with Real Examples)
  • Syntax.fmListen to the Syntax Podcast
  • Syntax.fm logo
    Listen to the Syntax Podcast

    Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.

    SEE EPISODES

Considered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.

© 2025 • Sentry is a registered Trademark of Functional Software, Inc.