SSL Peer Shut Down Incorrectly: Causes and Fixes

“SSL peer shut down incorrectly” means a remote server, proxy, firewall, or other network peer closed a TLS connection without completing the shutdown the Java client expected. It can happen during the TLS handshake or while downloading data, so the message alone does not prove that the server certificate is bad. The quickest path is to identify the exact host and failure stage, test that host outside the application, then repair the network, proxy, runtime, or repository configuration that differs.

Use this table to match the pattern you see before changing certificates or build settings.

What You Observe Likely Cause Area Start With
Java and curl both fail against the same host Server, reverse proxy, corporate proxy, firewall, or network path Capture the verbose connection output and check the network path
curl works but a Java build fails Java runtime, build-tool proxy settings, trust store, or dependency cache Compare the Java runtime and tool configuration
The failure happens only on a work network, VPN, or CI runner TLS inspection, outbound proxy, firewall policy, or runner image Test from the same network and execution environment
A download starts and then ends with an EOF or peer-shutdown error Mid-transfer reset, proxy timeout, interrupted connection, or bad partial cache Test the repository host, then refresh the affected dependency cache
The error explicitly mentions an untrusted, expired, mismatched, or revoked certificate Certificate validation rather than an unclean TLS shutdown Fix the certificate chain, hostname, clock, or revocation issue

What SSL Peer Shut Down Incorrectly Means

TLS connections should end with a protocol-level closure message before the underlying network connection is closed. An SSL peer shutdown error means the client received an unexpected end of the connection instead.

The error identifies an unclean connection close, not the component that caused it.

The “peer” is the other end of the connection from the application’s perspective. That might be the repository server, but it can also be a load balancer, TLS-inspecting proxy, VPN gateway, endpoint security product, or firewall between your machine and the server.

The timing matters:

  • During the handshake: The remote side may reject the protocol, cipher capabilities, Server Name Indication hostname, client certificate request, or proxy connection.
  • During a download: A server, proxy, or network device may close an established connection before the complete response arrives.
  • Only in one tool: The failing tool may use a different Java runtime, proxy configuration, certificate store, or HTTP client library than your terminal test.

This is different from errors such as “certificate expired,” “hostname verification failed,” or “certificate revoked.” Those messages indicate that the client received a certificate and rejected it during validation.

How to Fix an SSL Peer Shutdown Error

Work through these steps in order. They start with evidence gathering and avoid unsafe workarounds such as disabling TLS verification.

Step 1: Capture the Exact Failing Host and Stage

Record the complete URL or hostname, the tool that failed, and whether the error occurred before a response began or during a download. Also record the Java runtime actually used by the build or service.

For a Gradle build, run the failing task with more logging. If build is the task that fails, use:

./gradlew build --info --stacktrace

If --info does not reveal the repository request or connection stage, use debug logging for one controlled run:

./gradlew build --debug --stacktrace

Redact passwords, access tokens, signed URLs, and private repository names before sharing logs. Gradle’s issue tracker shows this error can appear underneath a “Remote host closed connection during handshake” failure, which is useful confirmation that the failure is below normal dependency resolution.

Do not replace HTTPS with HTTP or configure the application to trust every certificate. Those changes can hide the symptom while exposing credentials and downloaded artifacts.

Step 2: Test the Repository Host Outside the Java Tool

Test the affected host from the same machine or container that runs the failing process. A verbose curl request separates a general connection failure from a Java-specific one.

curl -vI https://your-repository-host.example/

Replace the example URL with the repository host from your logs. A response such as an authorization error or method-not-allowed response can still be useful: it shows that DNS, TCP, TLS negotiation, and the HTTP request reached the server. A peer-shutdown error, reset, or stalled request from curl points instead toward the server, proxy, or network path.

If curl succeeds but the Java application fails, compare the two clients rather than assuming the repository is healthy for every client. Java may be using a different proxy, trust store, protocol implementation, or runtime.

Step 3: Check the Network Path and Proxy Configuration

A corporate proxy or TLS-inspection device can terminate a connection before the application receives a clean TLS shutdown. This is especially likely when the same build succeeds on one network but fails on a VPN, office network, CI runner, or container host.

On Unix-like systems, list the names of proxy-related environment variables without printing their values:

env | cut -d= -f1 | grep -iE '(^|_)(http|https|all)_proxy|no_proxy'

Then check for proxy settings in the build tool, IDE, container runtime, and CI job configuration. Conflicting proxy settings are common: a shell may use one proxy while Gradle, Maven, a scanner, or a Java service uses another.

Test from the environment that actually fails. A command run on your laptop does not validate the path used by a CI container or remote build runner.

Run the comparison from the same network environment that fails so it tests the relevant network path.

If the issue appears only on a managed network, give the network or security team the failing hostname, timestamp, and sanitized verbose output. They can check proxy logs, firewall policy, TLS inspection behavior, and upstream connection resets without requiring you to weaken certificate validation.

Step 4: Repair the Java Runtime and Tool Configuration

Confirm which Java runtime the tool uses:

java -version

For Gradle projects, also inspect the runtime and Gradle distribution selected by the project wrapper:

./gradlew --version

Update an unsupported Java runtime, build tool, scanner, or server component through its supported upgrade path. Older components can depend on outdated TLS libraries or incompatible HTTP clients even when the operating system itself is current.

Also check these areas:

  • Duplicate or stale installations: A globally installed build tool can use different libraries from the project wrapper. Prefer the wrapper included with the project when it is available.
  • Partially upgraded packages: Old dependencies left behind by package-managed installs can be loaded alongside newer tooling and cause TLS failures.
  • Custom trust stores: A managed environment may need an approved corporate inspection certificate in the Java trust store. Obtain that certificate through your organization’s approved process; do not import a certificate copied from an error page or unknown source.
  • Clock problems: A badly incorrect system clock usually produces a certificate-validation error, but it is still worth correcting before deeper TLS troubleshooting.
  • Repository redirects: Confirm that the final host after redirects is expected and allowed through the proxy or firewall.

Make one controlled change at a time and repeat the same host test after each change. That makes it possible to identify whether the fix was the runtime, proxy, or network path.

Step 5: Refresh Only After the Connection Is Clean

An interrupted artifact download can leave an incomplete or unusable cache entry. Once the host connects reliably, refresh dependencies and rerun the original task.

For a Gradle build task, use:

./gradlew build --refresh-dependencies

Use the task that originally failed if it is not build. Let the task finish normally, then confirm that the expected dependency or artifact was downloaded and that any checksum or signature validation provided by your repository still passes.

Finally, remove temporary debug logging and restore any approved proxy configuration that you changed for testing.

Gradle, CI, and Download-Specific Cases

Gradle Dependency Download Failures

A Gradle error may name the exact resource that failed. One reported dependency request was:

https://jcenter.bintray.com/com/google/protobuf/protobuf-java/3.10.0/protobuf-java-3.10.0.jar

Treat a URL like this as both a transport clue and a repository-configuration clue. Check why the build still reaches that repository, whether the dependency is available from a supported repository, and whether a transitive dependency or old plugin added the repository configuration.

Use the project’s Gradle wrapper rather than a separate global Gradle installation when possible. The wrapper helps ensure the project uses its intended Gradle distribution instead of a system installation with different libraries or proxy behavior.

CI Containers and Build Runners

When the error appears only in CI, repeat the repository test inside the same container image or runner environment. The runner may have a different certificate bundle, Java runtime, proxy environment, DNS path, or egress firewall policy than a developer workstation.

Avoid copying a workstation trust store into a container as a quick fix. If TLS inspection is required on the runner network, install the organization-approved trust configuration through the image or CI platform’s normal configuration process.

Long Downloads That Fail Mid-Transfer

If the handshake succeeds but the transfer stops later, focus on connection resets and caches rather than certificate replacement. Check whether the same URL fails at a consistent point, whether a proxy closes large or slow responses, and whether the build tool is retrying a damaged cached artifact.

After the network path is stable, refresh the affected dependency cache and rerun the download. If the same repository consistently drops the response, the repository or proxy operator needs the URL and sanitized request timing to investigate.

When It Is Not an SSL Peer Shutdown Error

An SSL handshake failure is a broad category: it means the client and server did not complete TLS negotiation. It can be caused by unsupported protocol capabilities, hostname routing, client-certificate requirements, proxy interference, or a server that closes the connection immediately.

A peer-shutdown error may happen during the handshake, but it may also happen later while data is being read. Do not assume every “SSL” error is a certificate problem.

Certificate-specific messages need a different diagnosis:

  • Expired certificate: The server must present a current certificate, or the client clock must be corrected if the clock is wrong.
  • Hostname mismatch: The URL hostname must match a name on the certificate.
  • Unknown issuer: The client needs the correct trusted certificate chain, often including an approved corporate root in managed networks.
  • Revoked certificate: The certificate authority has marked the certificate as no longer trustworthy. Retrying does not change the certificate authority’s revocation decision.

SSH host-key errors are also separate from TLS certificate errors. SSH verifies a server’s public host key rather than an HTTPS certificate chain.

How to Confirm the Fix and Prevent a Repeat

A durable fix should work from the same environment that originally failed, not just from a different laptop or network.

Use this short confirmation checklist:

  • The original build, scanner, package manager, or application request completes successfully.
  • The same repository hostname works from the Java tool and an independent HTTP client.
  • The active Java runtime and build-tool version are known and supported.
  • Proxy configuration has one clear owner instead of competing environment and tool settings.
  • The certificate and trust-store configuration matches the approved environment.
  • CI images and local development environments use maintained runtime and certificate configurations.
  • Repository definitions point to supported, intended dependency sources.

Keep sanitized verbose logs for recurring failures. The hostname, connection stage, runtime version, and whether another client can reproduce the failure are usually more valuable to an administrator than the single exception line.

Frequently Asked Questions

What Is an SSL Handshake Failure?

An SSL handshake failure means the client and server could not complete TLS negotiation before protected application data was exchanged. It can result from protocol incompatibility, a proxy closing the connection, a hostname-routing problem, a required client certificate, or certificate validation failure. “SSL peer shut down incorrectly” is one possible symptom when the remote side closes the connection during that process.

How Should I Fix an SSL Connection That Fails Intermittently?

Start by testing the same repository host from the same machine, container, or CI runner where the application fails. If the failure appears only on one network, investigate the VPN, proxy, firewall, or TLS-inspection path; if only Java fails, inspect its runtime, trust store, and proxy configuration. Refresh dependency caches only after the connection succeeds reliably.

What Does an SSL Certificate Revoked Error Mean?

An SSL certificate revoked error means the certificate authority has declared the server certificate no longer trustworthy before its normal expiration date. The server owner must replace or correct the certificate, or a managed network must repair access to its approved revocation-checking infrastructure. Do not bypass revocation checking or disable certificate validation to make the error disappear.

How Do I Fix “SSL Peer Certificate or SSH Remote Key Was Not OK”?

“SSL peer certificate or SSH remote key was not OK” means the client could not verify the remote identity: for HTTPS, that is usually a certificate chain, hostname, expiration, or trust problem; for SSH, it is a host-key verification problem. Verify the hostname and certificate chain for HTTPS, or compare the SSH host-key fingerprint through a trusted administrative channel before accepting a changed key. Your next action should be to capture one verbose failing request and identify whether the rejected identity is an HTTPS certificate or an SSH host key.