bg-tutorials

How to Fix SSL_ERROR_RX_RECORD_TOO_LONG in Firefox

When Firefox blocks a page with a Secure Connection Failed screen and the code SSL_ERROR_RX_RECORD_TOO_LONG, the wording sends most people looking in the wrong direction. The message describes what Firefox measured, not what went wrong. Firefox is reporting that the data arriving from the server does not have the shape of a TLS record, and in almost every case that is because the server is not speaking TLS at all on the port the browser connected to.

Quick answer:

SSL_ERROR_RX_RECORD_TOO_LONG is a Firefox error meaning the server answered an HTTPS request with something that is not TLS, almost always plain HTTP served on port 443. Firefox reads the first five bytes of the reply as a TLS record header, and the text “HTTP/” yields a declared record length of 20,527 bytes, well above the 18,432-byte maximum that TLS permits, so the connection is dropped.

It is a server-side misconfiguration, not a browser fault: enable TLS on the port that is answering (SSLEngine on in Apache, listen 443 ssl in nginx), or correct the proxy that terminates HTTPS. Visitors cannot fix it, with one narrow exception: a local proxy or antivirus that intercepts the connection.

Firefox Secure Connection Failed page showing the error code SSL_ERROR_RX_RECORD_TOO_LONG

Table of Contents

  1. What SSL_ERROR_RX_RECORD_TOO_LONG Actually Means
  2. Why You Usually Only See It in Firefox
  3. Confirm the Cause in One Command
  4. How to Fix It on Your Server
  5. What to Do if You Are Just a Visitor
  6. What Does Not Fix This Error
  7. Frequently Asked Questions

What SSL_ERROR_RX_RECORD_TOO_LONG Actually Means

The error comes from NSS, the cryptographic library Firefox uses for TLS. Its official text is “SSL received a record that exceeded the maximum permissible length.” To understand why a misconfigured web server produces it, you need to know how TLS frames its data.

Every TLS message travels inside a record that begins with a five-byte header: one byte for the content type, two bytes for the protocol version, and two bytes giving the length of the payload that follows. The browser reads those five bytes first, then waits for exactly that many bytes of data.

Now consider a server that is listening on port 443 but has no TLS enabled on that port. Firefox opens the connection and sends a TLS ClientHello. The server has no idea what that is, treats it as a malformed HTTP request, and replies the only way it knows how, in plain text starting with something like “HTTP/1.1 400 Bad Request”. Firefox has no reason to expect plain text, so it reads those first five characters as a record header:

Header bytesField it maps toCharacters receivedValue Firefox reads
0Content typeH0x48 (not a valid TLS type)
1 to 2Protocol versionTT0x5454 (no such version)
3 to 4Payload lengthP/0x502F, or 20,527 bytes

That last field is what triggers the error. TLS caps the size of a single record: RFC 5246 allows at most 2^14 plus 2048 bytes for TLS 1.2, which is 18,432, and RFC 8446 tightens it to 2^14 plus 256 bytes, or 16,640, for TLS 1.3. NSS enforces those exact limits, and a claimed length of 20,527 bytes exceeds them. Firefox sends a fatal record_overflow alert, abandons the connection, and shows you SSL_ERROR_RX_RECORD_TOO_LONG.

Mozilla has acknowledged for years that the message is misleading. A long-standing bug report asks for a clearer message when the server returns an HTTP response, noting that parsing the bytes of “HTTP/1.1” as a record header is what produces this error. The bug is still open, so the confusing wording remains.

The practical takeaway is that the number in the error is meaningless on its own. It is not a size limit you can raise, and it has nothing to do with large pages, big files, or long headers. It is a plain-text reply being misread as encrypted framing.

Why You Usually Only See It in Firefox

The underlying fault is not browser-specific, but the error name is. Firefox uses NSS, which reports the precise reason the record was rejected. Chrome and Edge use BoringSSL, which collapses the same situation into the more general ERR_SSL_PROTOCOL_ERROR, and sometimes into a connection-closed message instead.

That difference is diagnostically useful. If Firefox shows SSL_ERROR_RX_RECORD_TOO_LONG and Chrome shows ERR_SSL_PROTOCOL_ERROR on the same address, both browsers are describing one server-side fault, and you have already ruled out anything specific to your Firefox profile.

Save 10% on SSL Certificates when ordering from SSL Dragon today!

Fast issuance, strong encryption, 99.99% browser trust, dedicated support, and 25-day money-back guarantee. Coupon code: SAVE10

A detailed image of a dragon in flight

Confirm the Cause in One Command

Before changing any configuration, confirm what the server is actually returning. The OpenSSL client speaks TLS directly and reports the same underlying problem in its own words. Run:

openssl s_client -connect example.com:443 -servername example.com

If the port is serving plain HTTP, OpenSSL fails on the same reply and says so:

CONNECTED(00000005)
error:0A00010B:SSL routines:ssl3_get_record:wrong version number

That is OpenSSL reading the same reply Firefox rejected, but stopping one field earlier: the two bytes where a TLS version belongs read TT, so it rejects the version before it ever weighs the length. The exact wording depends on which library your openssl command is built from, not on the server. OpenSSL 3.0 and 3.1 print the line above, and LibreSSL, which is what the built-in openssl command is on macOS, reports a protocol version alert instead. Older OpenSSL 1.0.x releases worded it as a wrong version number or unknown protocol error, but that branch reached end of life at the end of 2019. All of these are the same fault seen through different checks, so any of them confirms the diagnosis.

A healthy HTTPS port answers with a certificate. The lines worth looking for are the ones naming the certificate and the negotiated cipher:

CONNECTED(00000006)
subject=CN=example.com
issuer=C=US, O=Let's Encrypt, CN=R13
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Verify return code: 0 (ok)

One caution on reading that output, because this error is the case where it misleads most. Do not use the Verify return code line to judge whether the port is working. On the failed connection above, OpenSSL still ends with “Verify return code: 0 (ok)”. That zero does not mean the certificate passed. It means no certificate was ever received, so verification never ran at all. The failing run ends like this:

no peer certificate available
New, (NONE), Cipher is (NONE)
Verify return code: 0 (ok)

The two lines above the verification result are what actually separate the cases. A working port prints a subject= line and a real cipher name. A port that is not speaking TLS prints “no peer certificate available” and “Cipher is (NONE)”.

Separately, once the port is serving TLS, a plain run of s_client still does not check that the certificate matches the hostname, so it can report success for a certificate issued to a different site. Add -verify_hostname to test that as well:

openssl s_client -connect example.com:443 -servername example.com -verify_hostname example.com

A mismatch then reports “Verify return code: 62 (hostname mismatch)” instead of zero. One platform note: on macOS the built-in openssl command is LibreSSL, not OpenSSL, and it rejects this flag with “unknown option -verify_hostname”. Install OpenSSL through Homebrew if you need it there, and confirm with openssl version that you are calling the new build rather than the system one, which stays earlier on the default PATH; the full path is /opt/homebrew/bin/openssl.

You can also approach it from the opposite direction and ask whether port 443 answers plain HTTP. This test is quick and the two outcomes are easy to tell apart:

curl -sS -o /dev/null -w '%{http_code}\n' http://example.com:443/

Read the result the opposite way round to how it looks. A 200 is the bad outcome: the port served real content over an unencrypted request, which is the misconfiguration itself. A 400 is the healthy one, because that is what Apache and nginx return when plain HTTP arrives on a port that expects TLS. Drop the -o /dev/null to read the body, which names the problem outright in both servers.

How to Fix It on Your Server

Work through the checks below in order. The first one resolves the large majority of cases.

1. Enable TLS on the virtual host that answers on port 443

This is the classic cause. A virtual host is bound to port 443, so the port is open and answering, but TLS was never switched on for it. The server therefore treats 443 as an ordinary HTTP port.

In Apache, the TLS engine is off by default for the main server and for every virtual host, so it has to be enabled explicitly. A block like this one is listening on the right port and will produce the error:

<VirtualHost *:443>
    ServerName example.com
    DocumentRoot /var/www/example
</VirtualHost>

Adding the TLS directives fixes it:

<VirtualHost *:443>
    ServerName example.com
    DocumentRoot /var/www/example

    SSLEngine on
    SSLCertificateFile    /etc/ssl/certs/example.com.crt
    SSLCertificateKeyFile /etc/ssl/private/example.com.key
</VirtualHost>

Also confirm that the server is told to listen on the port at all. In Apache that lives in the ports configuration file, usually ports.conf or httpd.conf, and the mod_ssl module has to be enabled. Test the configuration before reloading, so a syntax error cannot take the site down:

sudo apachectl configtest
sudo systemctl reload apache2

In nginx the equivalent mistake is a listen directive without the ssl parameter:

server {
    listen 443;
    server_name example.com;
}

The corrected version adds the parameter and points at the certificate and key:

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate     /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;
}

If you are following an older guide that tells you to write a standalone ssl on; line, ignore it. That directive was made obsolete in nginx 1.15.0 and removed entirely in 1.25.1, so on any current release it will stop the server from starting. Then test and reload:

sudo nginx -t
sudo systemctl reload nginx

If you have not installed the certificate yet, our step-by-step guides for Apache and nginx cover the whole process, and there are instructions for other platforms as well.

2. Check what is actually listening on port 443

If the configuration looks right, verify which process holds the port. Another service may have claimed it, or the web server may have failed to bind it and quietly kept running on port 80 only. On a Linux server, run:

sudo ss -tlnp | grep :443

An empty result means nothing is listening at all, which produces a connection failure rather than this error, so the site would be unreachable in every browser. If the process shown is not the web server you configured, that other service is the one answering Firefox.

It is worth being precise about the port question, because it is frequently stated backwards. A closed port 443 does not cause SSL_ERROR_RX_RECORD_TOO_LONG. A closed port gives you a refused connection and a plain “unable to connect” page. Seeing this error already tells you that something is listening on the port and replying, which is why the fix is about what that something is saying, not about opening the port.

To check the port from outside the machine, you need the server’s public IP address. You can look it up by entering your domain and selecting the A record in a tool such as DNS Checker.

Looking up a domain's A record in DNS Checker to find the server IP address

With the IP address, a service such as Portchecker will tell you whether 443 is reachable from the public internet.

Checking whether port 443 is open on a server IP address with Portchecker

3. Fix HTTPS termination at a proxy, load balancer, or CDN

When something sits in front of your web server, the plain-HTTP reply can come from that layer instead of from the origin. Two arrangements produce it regularly.

  • A reverse proxy or load balancer accepts traffic on 443 but has no certificate bound to that listener, so it forwards or answers in clear text. Check that the frontend listener is defined as an HTTPS or TLS listener, not a TCP or HTTP one.
  • The proxy terminates TLS correctly for visitors but then connects to the backend on port 443 over plain HTTP. The visitor-facing side works, and the failure appears only on the internal leg.

Container and orchestration setups fail the same way when a service maps external port 443 to a container that only serves HTTP. In each case the fix is to make the component that owns port 443 present a certificate, or to change the mapping so the port that answers is the one configured for TLS.

4. Check for HTTPS on a non-standard port

Control panels and application servers often run HTTPS on ports such as 8443 or 2083. If you request an address like https://example.com:8080/ and that port serves plain HTTP, you get exactly the same error for exactly the same reason. Confirm which port is meant to carry TLS and use it, or enable TLS on the port you are asking for.

The reverse case also shows up in browsers as a broken page. Requesting http:// on a port that only speaks TLS returns a protocol error rather than content.

5. Keep TLS 1.2 and TLS 1.3 enabled, and drop the obsolete versions

Protocol configuration deserves a clear statement, because advice on this point is often garbled. Your server should support TLS 1.2 and TLS 1.3. Those are the versions browsers use, and they must stay enabled. What should be disabled are the obsolete ones: SSL 2.0, SSL 3.0, TLS 1.0, and TLS 1.1. Never disable TLS 1.2 or TLS 1.3, as that leaves no protocol a modern browser can negotiate and takes the site offline.

Note that a pure protocol-version mismatch does not produce SSL_ERROR_RX_RECORD_TOO_LONG. When a server offers only versions Firefox refuses, the browser reports SSL_ERROR_UNSUPPORTED_VERSION, and when no cipher suite is shared it reports SSL_ERROR_NO_CYPHER_OVERLAP. Those are separate errors with separate fixes. Tightening the protocol list is good practice, but it is not the remedy for a record-length error.

6. Verify the fix

Once the server answers over TLS, confirm the certificate, chain, and protocol support are correct. Run a scan with our free SSL Checker, which reports the expiry date, the certificate chain, and configuration problems that a padlock icon will not reveal. Repeat the s_client command from earlier as well, since it tests the exact port you changed.

With HTTPS working, finish the job by sending visitors there automatically. Our guide on how to switch from HTTP to HTTPS covers the redirects and the content changes that go with them.

What to Do if You Are Just a Visitor

If the site is not yours, be aware that you almost certainly cannot fix this. The server is returning data that is not TLS, and no browser setting changes what a remote server sends. The useful step is to tell the site owner, ideally quoting the error code so they know where to look.

There is one genuine exception, and it is worth ruling out first if several unrelated sites fail at once.

Rule out a local proxy or intercepting antivirus

Software running on your own machine or network can sit between Firefox and the site: a proxy, a corporate filter, a VPN client, or an antivirus product with an HTTPS scanning feature. If that software mishandles the connection and returns a plain-text page, such as a block notice or an error message, Firefox reads it exactly as it would read a misconfigured server’s reply and shows the same error.

The signature of this cause is breadth: a server misconfiguration breaks one site, while an intercepting proxy tends to break many at once, or breaks them only on one network. To check Firefox’s proxy configuration:

  • Open the menu button and choose Settings, or go straight to about:preferences.
  • Stay in the General panel and scroll to the bottom, to Network Settings.
  • Click Settings to open the Connection Settings dialog.
  • Select No proxy, click OK, and reload the page.
Firefox Connection Settings dialog with the No proxy option selected

If your antivirus has an HTTPS scanning, web shield, or SSL filtering feature, turn that individual feature off and reload. Turn it back on once you know whether it was responsible. There is no reason to uninstall the product or disable its protection as a whole to test one setting.

A quick way to place the fault is to load the same site from a different network, such as a phone on mobile data. If it works there and fails on your usual connection, something on that network is intercepting the traffic. If it fails everywhere, the server is misconfigured and only its owner can fix it.

What Does Not Fix This Error

Several steps are routinely recommended for SSL_ERROR_RX_RECORD_TOO_LONG that cannot influence it. They are carried over from generic lists of browser certificate warnings, which are a different class of problem. Knowing why each one fails saves time.

  • Clearing the cache and cookies. The failure happens during the TLS handshake, before Firefox sends a single HTTP request. Nothing cached has been consulted yet, so there is nothing to clear that could matter.
  • Disabling extensions. Extensions operate above the network stack through the WebExtensions APIs. They do not participate in parsing TLS records, so they cannot cause a record-length rejection.
  • Refreshing or resetting Firefox. This resets your profile, add-ons, and settings. The only profile setting that can matter here is the proxy configuration, and you can check that directly in seconds without discarding everything else.
  • Updating Firefox. Staying current is sensible for other reasons, but the record-length limit comes from the TLS specification and has not changed. A newer version rejects the same reply in the same way.
  • Correcting the clock on your computer. The system clock is consulted when validating a certificate’s dates. In this failure no certificate is ever received, so the clock is never used. A wrong clock produces date errors such as NET::ERR_CERT_DATE_INVALID, not this one.
  • Reinstalling or reissuing the certificate. Tempting, but if the virtual host has no TLS enabled the certificate is never presented, so a new one changes nothing. Enable TLS on the port first, then check the certificate.

The pattern behind all six is the same. This error is decided in the first five bytes the server sends back, before certificates, caches, clocks, or page content enter the picture.

Frequently Asked Questions

Is SSL_ERROR_RX_RECORD_TOO_LONG a browser problem or a server problem?

It is a server problem in nearly every case. Firefox is reporting that the reply it received was not a valid TLS record, which happens when the server serves plain HTTP on a port the browser is addressing over HTTPS. The one client-side exception is a local proxy or antivirus intercepting the connection and returning a plain-text page of its own.

Does an expired or missing certificate cause this error?

No. An expired certificate produces a date error, and an untrusted one produces an issuer error such as SEC_ERROR_UNKNOWN_ISSUER. Both mean a certificate was presented and then judged. SSL_ERROR_RX_RECORD_TOO_LONG means the handshake never reached that stage, because the reply was not TLS at all.

Does opening port 443 fix it?

No, and the assumption is worth correcting because it appears often. If port 443 were closed or blocked, you would get a refused connection and an “unable to connect” page. Receiving this error proves the port is open and something is answering on it. The fix is to make that service speak TLS.

How do I check whether my server is serving plain HTTP on port 443?

Send an unencrypted request to the port and see whether it answers normally:
curl -sS -o /dev/null -w '%{http_code}\n' http://example.com:443/
A success code such as 200 means the port answered an unencrypted request with real content, which confirms the misconfiguration. A correctly configured HTTPS port answers the same request with 400, which is the result you want here. The body of that 400 names the problem directly: nginx returns “The plain HTTP request was sent to HTTPS port”, and Apache returns “You’re speaking plain HTTP to an SSL-enabled server port”. Seeing either one means TLS is enabled on the port and this error is not coming from your server.

I get the error on a port such as 8443. Is that different?

No, the cause is identical. Any port addressed over HTTPS that answers in plain HTTP produces it. Control panels and application servers commonly use 8443, 2083, or similar ports, so confirm which port is configured for TLS and request that one, or enable TLS on the port you are using.

What does the “record too long” number actually refer to?

To the length field in a TLS record header. TLS allows at most 18,432 bytes per record under TLS 1.2 and 16,640 under TLS 1.3. When the characters “P/” from an HTTP response land in that field, they read as 20,527 bytes, which exceeds the limit. It is not a size limit you can raise, and it is unrelated to how large your pages are.

For more SSL error troubleshooting, check our detailed tutorials about fixing different SSL errors.

Save 10% on SSL Certificates when ordering from SSL Dragon today!

Fast issuance, strong encryption, 99.99% browser trust, dedicated support, and 25-day money-back guarantee. Coupon code: SAVE10

A detailed image of a dragon in flight
Written by

I've been building and managing websites for over 20 years, with a heavy focus on the technical side of the cybersecurity, VPN, and SaaS industries. I know how sites are built from the ground up, which means I know how to secure them. Here at SSL Dragon, I write about web architecture, encryption, and keeping your infrastructure safe.