Home / Tutorials / HTTP

HTTP · Network · Production down

Fix: ERR_SSL_PROTOCOL_ERROR

Error ERR_SSL_PROTOCOL_ERROR

By the Erzon engineering team · A step-by-step fix, not a forum thread

ERR_SSL_PROTOCOL_ERROR is the browser (Chrome’s wording; Firefox shows SSL_ERROR_RX_RECORD_TOO_LONG or similar) reporting that the TLS handshake never completed. This is not a certificate warning; it fails before certificates are even evaluated. The server on port 443 sent bytes that are not valid TLS, spoke only protocol versions the client refuses, or something between the two mangled the exchange. Users get a hard error with no way through, so a site-wide occurrence is a full outage.

ERR_SSL_PROTOCOL_ERROR

What this error means

A TLS connection starts with a handshake: the client sends a ClientHello listing the protocol versions and ciphers it supports, and the server must answer with a valid ServerHello the client can work with. This error means that exchange broke. The most common shapes: the server answered with plain HTTP on the TLS port (the classic misconfiguration, which Firefox names precisely with RX_RECORD_TOO_LONG), the server only offers TLS 1.0/1.1 which modern browsers have removed, no overlapping cipher suites exist, or a proxy, load balancer, or middlebox corrupted the stream.

Because the failure is below HTTP, none of your application logs will show these requests. You diagnose it at the TLS layer with openssl s_client and curl -v.

Common causes

  • A server block listening on port 443 without TLS enabled, so plain HTTP comes back to a client expecting TLS (in Nginx, a listen 443; missing the ssl parameter).
  • A proxy chain scheme mismatch: the edge connects with HTTPS to a port where the origin speaks HTTP, or vice versa.
  • Only obsolete protocols enabled: TLS 1.0 and 1.1 are rejected by all modern browsers.
  • No shared cipher between client and server, common after an aggressive hardening pass or on very old server stacks.
  • A corrupted or wrong certificate/key pair loading incorrectly, leaving the TLS listener half-configured after a reload.
  • Middleboxes on the client’s path: TLS-inspecting corporate proxies, antivirus HTTPS scanning, or captive portals.
  • Port collision: some non-TLS service (or a debugging tool) bound to 443 instead of the web server.

How to fix it

STABILIZE first. If this started right after a config deploy or certificate rotation, roll that change back; a half-applied TLS config is the most common trigger for a sudden site-wide protocol error.

  1. Look at what the server actually speaks on port 443:
openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null
curl -v https://www.example.com/ -o /dev/null

A healthy server prints a certificate chain and a negotiated protocol like TLSv1.3. wrong version number means plain HTTP (or another non-TLS protocol) answered on the port. no protocols available or handshake failure points at protocol or cipher mismatch.

  1. Confirm what is bound to the port and what the server config says:
ss -ltnp | grep :443
nginx -T 2>/dev/null | grep -E "listen|ssl_protocols|ssl_ciphers" | sort -u

DIAGNOSE from the evidence. wrong version number plus an Nginx listen 443; without the ssl flag is the answer right there. ss showing an unexpected process on 443 explains everything without touching the web server. A handshake failure with old ssl_protocols values means the protocol floor is too low for modern clients. And if openssl s_client from a clean network succeeds while specific users still fail, the breakage is on their path (corporate proxy or antivirus interception), not on your server.

FIX the server so port 443 speaks modern TLS and nothing else:

server {
    listen 443 ssl;
    http2 on;
    server_name www.example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
}
nginx -t && nginx -s reload
openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null 2>/dev/null | grep -E "Protocol|Cipher"

Verify the certificate and key actually match before reloading (openssl x509 -noout -modulus -in cert.pem | openssl md5 against the same command with rsa -in key.pem), because a mismatched pair will fail the reload or leave the listener broken. If a proxy chain is involved, align each hop: the scheme and port the edge dials must be exactly what the origin serves there.

How to prevent it

  • Test TLS after every certificate rotation and config deploy with an automated openssl s_client or SSL Labs check in the pipeline.
  • Keep ssl_protocols TLSv1.2 TLSv1.3 as the standard everywhere; never re-enable 1.0/1.1 for one legacy client without isolating it.
  • Validate config before reload (nginx -t) in the deploy script, and make cert renewal reload the server atomically.
  • Monitor the site over HTTPS from outside your network so a broken handshake pages you instead of your users.
  • Document which scheme every hop in the proxy chain uses so a port or scheme change on one layer cannot silently break the next.

When to call a senior engineer

Call for help when handshakes fail only for a subset of clients you cannot reproduce (middlebox and client-fingerprint problems need packet-level analysis), when a proxy chain with mutual TLS or edge certificates has drifted out of alignment, or when a legacy system that only speaks old TLS must keep talking to a hardened modern stack. Erzon engineers can capture and read the actual handshake bytes at each hop, pinpoint which side violates the protocol, and rebuild the TLS termination so every client that should connect, can.

Related errors we fix

Still down after this?

Want a senior engineer to just fix it?

Paste this exact error into the form. A senior engineer replies within one business hour with what is likely wrong and a flat quote. Triage is free.

Book a fix

← Back to all error fixes

Still down?

Get a senior engineer on it now

Leave your email and a line about what is happening. A senior engineer replies within one business hour with what is likely wrong and a flat quote. Triage is free.

Or email [email protected]. Same engineers, same one-hour clock.