Error message
javax.net.ssl.SSLException: Unsupported or unrecognized SSL message
Also printed as
- Unsupported or unrecognized SSL message
JDK 25 prints the same text on the client side and on a JSSE server that receives plain HTTP (both checked). When the peer sends nothing and closes, Java reports "Remote host terminated the handshake" instead.
Java (JSSE) — the peer's reply is not a TLS record
What it means
JSSE expected a TLS record and received bytes it cannot parse as one, most often the text of an HTTP response from a plain-HTTP server. On the client side, https:// was used against a port that does not speak TLS; on the server side (a Tomcat or Netty TLS listener), a client sent plain HTTP to the TLS port. The certificate is irrelevant here.
Why it happens
https:// to a plain-HTTP port
commonInternal services behind a TLS-terminating proxy, actuator or metrics ports, and local development servers usually speak plain HTTP.
The proxy is plain HTTP but configured as TLS
commonForward proxies typically accept plain HTTP and tunnel HTTPS with CONNECT; configuring TLS to the proxy itself produces this error.
Implicit TLS against a STARTTLS port
occasionalSMTP on 587/25 (mail.smtp.ssl.enable=true there), LDAP on 389 with ldaps://, or databases expecting an in-band upgrade.
Server log: a client sent plain HTTP to the TLS port
occasionalHealth checks or users calling http://host:8443 make the TLS connector log this for every request.
How to fix it
- 1.
Check what the port speaks
If the port answers plain HTTP, use http:// or the real TLS port.
bash curl -si http://api.example.com:8080/ | head -1 # an HTTP status line -> not TLS openssl s_client -connect api.example.com:8443 -brief </dev/null - 2.
Mail and directory clients: match TLS mode and port
Use STARTTLS on submission (587) and implicit TLS only on 465 (or ldaps:// on 636).
text # Mail (Jakarta Mail): STARTTLS on 587, implicit TLS on 465 mail.smtp.port=587 mail.smtp.starttls.enable=true mail.smtp.starttls.required=true # (mail.smtp.ssl.enable=true belongs to port 465 only) - 3.
Server owners: separate HTTP and HTTPS ports
Point clients and health checks at https://, or expose a plain HTTP connector that redirects to the TLS port.
text # Spring Boot server logging this for incoming requests: plain HTTP sent to the TLS port. # Use https:// on server.port, or add a separate HTTP connector that redirects to HTTPS.