javax.net.ssl.SSLHandshakeException: PKIX path building failed

After compiling JDA Discord bot using maven, I get this:
(It works fine in my machine)
So I might guess that it’s replit’s fault, or the library. But who knows, I’m new into JAVA.

Any help will be appreciated. Cheers!

Duplicate of: PKIX path building failed

This is the error:

An exception occurred while executing the Java class. -1: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

RuriYoshinova,

I would try posting this over in the Code Help section of the forums! Someone with Java experience will be able to best help you resolve your code related issue. Thanks!

Hello @RuriYoshinova can you please provide the link to your repl?

1 Like

https://replit.com/@RuriYoshinova/JDA

So, the error indicates that Java is not trusting the server’s SSL certificate.

You can search for the certificate here: crt.sh | 2835394 (Just look for download certificate PEM).

After the download you can import the certificate using the keytool.

2 Likes

After importing it with keytool, the console says this:
keytool error: java.io.FileNotFoundException: /nix/store/gpxl5qgg8kicmcvivwmybwjlpf7wh20l-graalvm17-ce-22.3.0/lib/security/cacerts (Permission denied)
I think its actually imported because when I try to reimport it, it says a similar one already exists… But I still got the original error, so its not really working
One thing I wanted to ask, how did you know that that certificate you linked is the one needed?

i was able to import it changing the permissions of the cacert file with the command chmod, silly me for forgeting about that…
yeah but its still not working, it may not be the correct certificate i think

You just need to look at the latest version at the same website.
You can search by company (discord in this case) and see what is the last one available.

Usually discord certificates are emitted by Cloudfare.

You can also download the certificate from the website (discord.com)

After importing the certificate, you can verify if it’s correctly installed by listing the certificates in the keystore using the keytool -list command.

i went to discord.com and downloaded the certificate, imported it, and it sure has been correctly imported as it appears on the keystore list. but i get the same error. i honestly dont know which requests does the java discord api do, maybe its doing a request to an intermediary site and not discord? i dont know… cause this seems like it isnt the correct certificate. i searched a bit about this yesterday and i still got no clue on how i would check which requests is doing or to what sites… do you know what i could do now?

It gives the same error?

Can you post the full error print here?

Sure, it is quite long, but just by reading the first block of the error i think you get already all the interesting information

[JDA RateLimit-Elastic-Worker 1] ERROR Requester - There was an I/O error while executing a REST request: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Exception in thread "main" net.dv8tion.jda.api.exceptions.ErrorResponseException: -1: javax.net.ssl.SSLHandshakeException
    at net.dv8tion.jda.internal.requests.RestActionImpl.complete(RestActionImpl.java:227)
    at net.dv8tion.jda.api.requests.RestAction.complete(RestAction.java:632)
    at net.dv8tion.jda.internal.JDAImpl.verifyToken(JDAImpl.java:409)
    at net.dv8tion.jda.internal.JDAImpl.login(JDAImpl.java:333)
    at net.dv8tion.jda.internal.JDAImpl.login(JDAImpl.java:299)
    at net.dv8tion.jda.api.JDABuilder.build(JDABuilder.java:1937)
    at me.katanya04.Main.main(Main.java:28)
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:371)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:309)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1357)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1232)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1175)
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:480)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:458)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:201)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1505)
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1420)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426)
    at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379)
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)
    at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
    at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
    at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
    at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
    at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
    at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
    at net.dv8tion.jda.internal.requests.Requester.execute(Requester.java:190)
    at net.dv8tion.jda.internal.requests.Requester.execute(Requester.java:145)
    at net.dv8tion.jda.internal.requests.Requester.execute(Requester.java:128)
    at net.dv8tion.jda.internal.requests.Requester$WorkTask.execute(Requester.java:378)
    at net.dv8tion.jda.api.requests.SequentialRestRateLimiter$Bucket.execute(SequentialRestRateLimiter.java:477)
    at net.dv8tion.jda.api.requests.SequentialRestRateLimiter$Bucket.run(SequentialRestRateLimiter.java:517)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
    at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
    at java.base/sun.security.validator.Validator.validate(Validator.java:264)
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1341)
    ... 37 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
    at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
    at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
    at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
    ... 42 more
Caused by: net.dv8tion.jda.api.exceptions.ContextException
    at net.dv8tion.jda.api.exceptions.ContextException.here(ContextException.java:54)
    at net.dv8tion.jda.api.requests.Request.<init>(Request.java:77)
    at net.dv8tion.jda.api.requests.RestFuture.<init>(RestFuture.java:40)
    at net.dv8tion.jda.internal.requests.RestActionImpl.submit(RestActionImpl.java:209)
    at net.dv8tion.jda.internal.requests.RestActionImpl.complete(RestActionImpl.java:219)
    at net.dv8tion.jda.api.requests.RestAction.complete(RestAction.java:632)
    at net.dv8tion.jda.internal.JDAImpl.verifyToken(JDAImpl.java:409)
    at net.dv8tion.jda.internal.JDAImpl.login(JDAImpl.java:333)
    at net.dv8tion.jda.internal.JDAImpl.login(JDAImpl.java:299)
    at net.dv8tion.jda.api.JDABuilder.build(JDABuilder.java:1937)
    at me.katanya04.Main.main(Main.java:28)

" me.katanya04.Main.main(Main.java:28)" is the line where i create the jda bot object, you know, where i put the discord token and run .build()

JDA bot = JDABuilder.createDefault(System.getenv("DISCORD_BOT_KEY"))
        .setActivity(Activity.playing("text here")).enableIntents(GatewayIntent.MESSAGE_CONTENT).build()
        .awaitReady();

Try to trust all certificates possible to see if the problem is in the certificate itself. In yourmain method, you can replace the placeholder code with the actual HTTP request logic using the client object.

import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import okhttp3.OkHttpClient;

public class SSLTest {

    public static void main(String[] args) {
        try {
            OkHttpClient client = createUnsafeClient();
            // You can use 'client' for your HTTP requests
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static class TrustAllCertificates implements X509TrustManager {
        public void checkClientTrusted(X509Certificate[] certs, String authType) {
        }

        public void checkServerTrusted(X509Certificate[] certs, String authType) {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }

    private static SSLContext createTrustAllSSLContext() throws Exception {
        SSLContext sc = SSLContext.getInstance("SSL");
        TrustManager[] trustAllCerts = new TrustManager[]{new TrustAllCertificates()};
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        return sc;
    }

    private static OkHttpClient createUnsafeClient() throws Exception {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.sslSocketFactory(createTrustAllSSLContext().getSocketFactory(), new TrustAllCertificates());
        builder.hostnameVerifier((hostname, session) -> true);
        return builder.build();
    }
}

Ps.: I’m assuming you are using OkHttpClient.

im sorry but im a bit… overwhelmed with that code you provided. what placeholder do you mean? do i have to write some more code aside from just pasting that? also im unsure how i would run that in replit. adding the dependency on the pom.xml wont be the case because im just compiling my code from the shell, you know, using the javac command, because the “Run” button just doesn’t work for me…
And I tried it on my machine and it gave me a NullPointerException, tho i dont know if it makes sense trying that code in my machine… cause idk what it does
Also, no im not using OkHttpClient, im using the java discord api, which is the one that does the http request to god knows where, supposedly discord, but the certificate from there as i said wont work

heres that one null pointer exception if you want to see it

java.lang.NullPointerException: trustManager.acceptedIssuers must not be null
	at okhttp3.internal.platform.Platform.buildTrustRootIndex(Platform.kt:163)
	at okhttp3.internal.platform.Platform.buildCertificateChainCleaner(Platform.kt:160)
	at okhttp3.internal.tls.CertificateChainCleaner$Companion.get(CertificateChainCleaner.kt:42)
	at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.kt:811)
	at me.katanya04.SSLTest.createUnsafeClient(SSLTest.java:41)
	at me.katanya04.SSLTest.main(SSLTest.java:13)

i searched a bit into the idea of, instead of getting the certificate, make java ignore the certificate check at all, and found this on stackoverflow + i added some modifications

    TrustManager trm = new X509TrustManager() {
      public X509Certificate[] getAcceptedIssuers() {
        return null;
      }

      public void checkClientTrusted(X509Certificate[] certs, String authType) {

      }

      public void checkServerTrusted(X509Certificate[] certs, String authType) {
      }
    };
    try {
      SSLContext sc = SSLContext.getInstance("SSL");
      sc.init(null, new TrustManager[] { trm }, null);
      HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception ex) {
      System.out.println("uh oh");
      return;
    }

it is very similar to your code that you provided. and from what i think i understand from this is that it should indeed do what i first said.
but surprise surprise… same error, java complains about not knowing the certificate, even tho this supposedly dissables that check. yes i put this in the main function, before i create an instance of discord bot. so uh… yeah thats interesting. (no, it didnt run into the “uh oh” branch, at least i didnt see it in the console)
how can this be so complicated…

The code you provide basically does the same.
You have to make sure that the SSL validation is executed before any network calls are made, even the initialization of the bot.

Another thing I’d recommend is to enable detailed SSL debugging in Java to get more info about what’s happening during the SSL handshake.

You can add this to your run command:

java -Djavax.net.debug=ssl,handshake -jar NameOfYourApplication.jar

Alright i think this is the certificate that is missing, cause just after it shows up in the console, that error appears

"Certificate": {
  "certificate_request_context": "",
  "certificate_list": [  
  {
    "certificate" : {
      "version"            : "v3",
      "serial number"      : "29B906DD51D9FC4163888B1D0403CFCAE35C8733",
      "signature algorithm": "SHA256withRSA",
      "issuer"             : "OU=Replit, O=Replit, L=San Francisco, ST=California, C=US",
      "not before"         : "2023-09-04 22:10:32.000 GMT",
      "not  after"         : "2024-08-25 22:10:32.000 GMT",
      "subject"            : "CN=discord.com, OU=Replit, O=Replit, L=San Fransisco, ST=California, C=US",
      "subject public key" : "RSA",
      "extensions"         : [
        {
          ObjectId: 2.5.29.35 Criticality=false
          AuthorityKeyIdentifier [
          KeyIdentifier [
          0000: 46 6F 22 DC ED 4C 10 25   DA 65 5C B1 1F 8C 3B 97  Fo"..L.%.e\...;.
          0010: AC 15 D1 FE                                        ....
          ]
          ]
        },
        {
          ObjectId: 2.5.29.19 Criticality=false
          BasicConstraints:[
            CA:false
            PathLen: undefined
          ]
        },
        {
          ObjectId: 2.5.29.15 Criticality=false
          KeyUsage [
            DigitalSignature
            Non_repudiation
            Key_Encipherment
            Data_Encipherment
          ]
        },
        {
          ObjectId: 2.5.29.17 Criticality=false
          SubjectAlternativeName [
            DNSName: discord.com
            DNSName: discordapp.com
          ]
        },
        {
          ObjectId: 2.5.29.14 Criticality=false
          SubjectKeyIdentifier [
          KeyIdentifier [
          0000: 78 CB BA 1A 69 F0 8C D1   D6 B9 66 EB 50 F5 12 94  x...i.....f.P...
          0010: 65 61 89 34                                        ea.4
          ]
          ]
        }
      ]}
    "extensions": {
      <no extension>
    }
  },
]
}

I have searched everywhere for it and didnt found it, maybe i also dont know how to search for it correctly…
And yeah i put that piece of code before the bot creation in the main method

Does this happen even if you start a new project? Like, Replit being the CA of the certificate?