Download Wrapper fails with SSLHandshakeException stacktrace

Problem downloading the Gradle wrapper.

I have tried with latest Oracle JDK 8u221 and OpenJDK 11.

This works on my laptop workstation, but fails with this stacktrace on our build servers.

build@jbssles123x64:~/workspace/project> gradle wrapper --gradle-version=5.5.1

BUILD SUCCESSFUL in 3s
1 actionable task: 1 up-to-date 

build@jbssles123x64:~/workspace/project> ./gradlew --version
Downloading https://services.gradle.org/distributions/gradle-5.5.1-bin.zip

Exception in thread "main" 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.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1964)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1052)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:987)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
        at sun.net.www.protocol.http.HttpURLConnection.followRedirect0(HttpURLConnection.java:2719)
        at sun.net.www.protocol.http.HttpURLConnection.followRedirect(HttpURLConnection.java:2641)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1824)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:263)
        at org.gradle.wrapper.Download.downloadInternal(Download.java:66)
        at org.gradle.wrapper.Download.download(Download.java:51)
        at org.gradle.wrapper.Install$1.call(Install.java:62)
        at org.gradle.wrapper.Install$1.call(Install.java:48)
        at org.gradle.wrapper.ExclusiveFileAccessManager.access(ExclusiveFileAccessManager.java:69)
        at org.gradle.wrapper.Install.createDist(Install.java:48)
        at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:107)
        at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)
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 sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)
        at sun.security.validator.Validator.validate(Validator.java:262)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1596)
        ... 22 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392)
        ... 28 more

What version of the JDK are you using on the build server, and have you made any changes to [JDK-path]/jre/lib/security/cacerts on the server? (This is the certificate store that contains the trusted certificates used for establishing an SSL handshake with a remote server.)

As an example, older versions of AdoptOpenJDK had a bug on the Windows distribution where the cacerts file was not populated, and this would leave to SSLHandshakeException. But it has since been fixed.

If you like to verify that the cacerts is OK, fist open the link, or part of it (e.g. https://services.gradle.org), in a browser and check the certificate chain. It should say DigiCert Baltimore Root -> CloudFlare Inc ECC CA-2 -> gradle.org. You will need at least the root certificate, which has the issuer Baltimore CyberTrust Root, in the cacerts file. Open this file with any certificate tool (I use the open source KeyStore Explorer tool). The standard password is changeit. Verify that the root certificate is present. (On Oracle 1.8.0_212, it has the entry name baltimorecybertrustca [jdk].)

Normally you don’t have to mess with all this stuff, but I suspect someone has already done exactly that on the JDK you use on the build server.

I have not modified the cacerts. It is original and untouched.

I have tried with:
Oracle JDK 8 Update 181
Oracle JDK 8 Update 221 (latest)
OpenJDK 11.0.4

Oracle JDK are unpacked from archive: jdk-8u221-linux-x64.tar.gz downloaded from Oracle.
OpenJDK are unpacked archive from AdoptOpenJDK.

This worked before, when I got Gradle 5.0, but now when I tried to upgrade to Gradle 5.5 it fails.

The certificate you mentioned are present in the cacerts

Alias name: baltimorecybertrustca [jdk]
Creation date: 25.aug.2016
Entry type: trustedCertEntry

Owner: CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE
Issuer: CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE
Serial number: 20000b9
Valid from: Fri May 12 20:46:00 CEST 2000 until: Tue May 13 01:59:00 CEST 2025
Certificate fingerprints:
         MD5:  AC:B6:94:A5:9C:17:E0:D7:91:52:9B:B1:97:06:A6:E4
         SHA1: D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74
         SHA256:
16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F 2:6A:EB
    Signature algorithm name: SHA1withRSA
    Subject Public Key Algorithm: 2048-bit RSA key
    Version: 3

According to https://services.gradle.org it is the same certificate used there.

Weird, then I am out of ideas. Sorry :confused:

But do let us know what was wrong if you manage to figure it out.

It seems the problem was it didn’t use proxy. The build server needs a proxy to access the outside world.

But if it could not access https://services.gradle.org, should there not be a different error message?

I tried to configure the proxy under /etc/sysconfig/proxy, but it still would not work. Using wget works after I configure the proxy there.

I had to configure proxy as java properties with gradle for it to work.

./gradlew -Dhttps.proxyHost=proxy.company.no -Dhttps.proxyPort=3128 --version

I had same issue, this post saved me.
I checked what is the problem with the certificate. With using gradlew -Djavax.net.debug=all we can see what is going on: When connecting to https://services.gradle.org the response is a 301 (permanently moved) and it redirects to https://downloads.gradle-dn.com/. Now my company uses Cisco umbrella and when I check the certificate chain for that server it ends up with Cisco Umbrella Root CA which is an “artificial” CA and not in java’s cacerts.
Strange: gradlew client gets the 301. Browser client gets 304 (no redirect).

1 Like