SSL_ERROR_RX_RECORD_TOO_LONG: Causes and the Fix
Firefox throws up a page that just says "Secure Connection Failed" with the code SSL_ERROR_RX_RECORD_TOO_LONG, and there's no padlock, no cert warning, nothing you can click past. That's because this isn't a certificate problem at all — it's your browser trying to negotiate TLS with something on the other end that isn't speaking TLS. Here's what's actually happening and how to fix it depending on your setup.
What This Error Actually Means
Every other SSL error in this family — expired cert, name mismatch, untrusted authority — happens because the browser did get a TLS handshake back, just one it doesn't like. SSL_ERROR_RX_RECORD_TOO_LONG is different: the browser sent an HTTPS request to port 443, and got a plain-text HTTP response back. Firefox tries to parse that response as a TLS record, the length field doesn't make sense for TLS, and it bails with this exact message.
In plain terms: something on port 443 is answering in HTTP, not HTTPS. Chrome usually shows this as ERR_SSL_PROTOCOL_ERROR for the same root cause — Firefox is just more specific about it.
Symptom: What You'll See
- Firefox: "Secure Connection Failed" —
SSL_ERROR_RX_RECORD_TOO_LONG - Chrome/Edge:
ERR_SSL_PROTOCOL_ERROR, sometimes with no further detail - curl:
error:1408F10B:SSL routines:ssl3_get_record:wrong version number - It often shows up right after installing a new certificate, moving to a new server, or adding a reverse proxy — not on a site that's been running fine for months.
That curl error is worth testing directly, since it tells you immediately whether this is a browser quirk or a real server-side problem:
curl -v https://yourdomain.com/
If you see wrong version number in the output, port 443 genuinely isn't running TLS on that host. Confirm it with openssl:
openssl s_client -connect yourdomain.com:443
If that hangs, resets, or comes back with garbage instead of a certificate chain, you've confirmed the cause — now it's just a matter of finding which piece is misconfigured.
Cause 1: The Web Server Isn't Actually Listening for SSL on 443
This is the most common cause on cPanel and VPS setups alike. Something is bound to port 443, but the virtual host serving your domain doesn't have SSL configured on it — so requests fall through to a default, non-SSL vhost, or to a plain Listen 443 block with no SSLEngine on.
On a cPanel server, check whether AutoSSL actually installed a certificate for the domain in question:
whmapi1 fetch_ssl_certificate domain=yourdomain.com
If that comes back empty or with an error, the certificate was never issued — which usually means AutoSSL failed silently (DNS not pointing at the server yet, CAA record blocking the CA, or the domain failing HTTP validation). Until a cert is actually installed, port 443 has nothing valid to serve, and depending on the Apache config it may fall back to plain HTTP.
On a raw Nginx or Apache VPS, check the vhost directly:
# Nginx
nginx -T | grep -A5 "server_name yourdomain.com"
# Apache
apachectl -S | grep -B2 -A5 yourdomain.com
If the 443 block for that domain is missing ssl_certificate / SSLCertificateFile directives, or the domain isn't in any SSL vhost at all, that's your fix target.
Cause 2: A Redirect Forces HTTPS Before the Certificate Exists
Very common right after a migration: the old server (or a WordPress plugin, or an .htaccess rule) forces every request to https://, but the new server hasn't finished issuing a certificate yet. The browser gets redirected to 443, hits a port with no working SSL, and throws this error instead of a normal connection-refused.
Check for a force-SSL rule in wp-config.php:
define('FORCE_SSL_ADMIN', true);
And in .htaccess:
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
If AutoSSL or Certbot hasn't issued a valid cert yet, comment out the redirect temporarily, confirm the site loads over plain HTTP, get the certificate issued, then re-enable the redirect. Forcing HTTPS before the cert exists just turns a fixable HTTP page into this dead end.
Cause 3: Reverse Proxy or Load Balancer Terminating SSL Wrong
If you're running Nginx as a reverse proxy in front of an app server (Node, PHP-FPM via a non-standard setup, Docker container), it's easy to end up with the proxy listening on 443 without an ssl directive, just forwarding plain traffic to a backend that also expects plain HTTP. The browser talks TLS to the proxy; the proxy never answers in TLS because it was never told to.
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
If your config has listen 443; without the ssl keyword, or is missing the certificate directives entirely, that's the whole bug — Nginx is accepting connections on 443 but treating them as plain HTTP.
Cause 4: Cloudflare (or Another CDN) SSL Mode Mismatch
If you're behind Cloudflare, check SSL/TLS → Overview in the dashboard. With mode set to Full or Full (strict), Cloudflare expects your origin server to answer HTTPS on 443. If the origin's SSL isn't actually configured (see Cause 1), Cloudflare's connection to your origin fails the same way — you'll usually see a Cloudflare 521 or 526 error page instead of the raw browser error, but if you're testing by hitting the origin IP directly (bypassing Cloudflare with a hosts-file edit), you'll get SSL_ERROR_RX_RECORD_TOO_LONG straight from the misconfigured origin.
The fix here is the same as Cause 1 — get a valid cert running on the origin — but the diagnostic step is different: test the origin IP directly, not the Cloudflare-proxied domain, or you'll be debugging the wrong hop.
Step-by-Step Fix
- Run
curl -v https://yourdomain.com/and confirm you seewrong version number— that confirms port 443 isn't serving TLS. - On cPanel: check WHM → SSL/TLS Status for the domain and re-run AutoSSL if the certificate shows as missing or expired.
- On a VPS: confirm the vhost for the domain has valid
ssl_certificate/SSLCertificateFiledirectives pointing at files that actually exist (ls -lathe paths — a renamed or moved cert file is a common cause). - If a force-HTTPS redirect exists in
.htaccessorwp-config.php, disable it until the certificate is confirmed working, then re-enable it. - Reload the web server after any change — a saved config doesn't take effect until you do:
systemctl reload nginxorapachectl graceful. - Re-test with curl before retesting in the browser. Browsers cache HSTS and connection state aggressively; curl gives you a clean read every time.
Prevention
- Never force an HTTPS redirect until you've confirmed the certificate is live — test the plain HTTP site first after any migration or new domain setup.
- If you use a reverse proxy, always specify
listen 443 ssl;explicitly rather than assuming a barelisten 443;block implies TLS — it doesn't. - After any AutoSSL or Certbot renewal, spot-check with
openssl s_client -connect yourdomain.com:443instead of just trusting the renewal log said "success." - When testing behind Cloudflare, always test the origin IP separately from the proxied domain so you know which hop actually broke.
| What You See | Likely Cause |
|---|---|
| Fails immediately after a fresh cPanel account or migration | AutoSSL hasn't issued a certificate yet |
| Worked yesterday, broke after an .htaccess or plugin change | Force-HTTPS redirect enabled before cert existed |
| Only fails when hitting the server's raw IP | Origin has no valid SSL vhost — usually a Cloudflare Full-mode setup |
| Happens on a custom app port behind Nginx | Reverse proxy listening on 443 without the ssl directive |
If you've checked all four causes and port 443 still won't answer with a valid TLS handshake, open a ticket with your hosting provider's support and paste the curl -v output — it's the single most useful piece of evidence for diagnosing this fast.
Frequently asked questions
Is SSL_ERROR_RX_RECORD_TOO_LONG the same as an expired certificate error?
No. An expired or mismatched certificate still completes a TLS handshake - the browser just doesn't trust it, so you get a clickable warning page. SSL_ERROR_RX_RECORD_TOO_LONG means there was no TLS handshake at all: port 443 answered in plain HTTP, so there's nothing to click past.
Why does this happen right after I install a new SSL certificate?
Usually because a force-HTTPS redirect (in .htaccess, wp-config.php, or a plugin) was enabled before the certificate actually finished issuing. The redirect sends the browser to port 443 a few seconds too early. Disable the redirect, confirm the cert is live with openssl, then re-enable it.
Does this error only happen in Firefox?
No - Firefox is just the most explicit about naming it. Chrome and Edge show the same root cause as ERR_SSL_PROTOCOL_ERROR, and curl reports it as 'wrong version number'. All three mean the same thing: port 443 isn't speaking TLS.
Can a firewall or NAT rule cause this?
Yes. If a port-forwarding or load-balancer rule sends HTTPS traffic to a backend port that's actually serving plain HTTP, you'll get this exact error. Check that your proxy or LB config explicitly terminates or passes through SSL on 443, rather than assuming any listener on 443 is automatically TLS.
How do I test this without waiting on DNS or browser caching?
Use curl and openssl directly against the domain or the origin IP: curl -v https://yourdomain.com/ and openssl s_client -connect yourdomain.com:443. Both bypass browser HSTS caching and give you an immediate, unambiguous answer about whether port 443 is serving TLS.