Geonode logo
Website and server errors

How to Fix a 421 Misdirected Request Error

Find out whether a shared connection, a reverse proxy or your own Host header caused it, then fix that part.

Updated

TL;DR

421 Misdirected Request means the website's server will not serve that hostname on this connection, usually because the TLS server name (SNI) and the Host header point to different sites. The site's owner fixes it in the server or its reverse proxy, unless your own script overrode the Host header.

What a 421 looks like

We captured the Apache rows on our own test server; the nginx rows come from nginx's source code.

WhereWhat you see
Apache httpd error page (browser or curl)Misdirected Request The client needs a new connection for this request as the requested host name does not match the Server Name Indication (SNI) in use for this connection.
curl -i, HTTP/2 and HTTP/1.1HTTP/2 421 / HTTP/1.1 421 Misdirected Request
Python urllib.requesturllib.error.HTTPError: HTTP Error 421: Misdirected Request
Node.js https (statusCode, statusMessage)421 Misdirected Request
Apache error log (site owners)AH02032: Hostname www.example.com provided via SNI and hostname shop.example.com provided via HTTP have no compatible SSL setup for policy 'secure'
nginx default error page421 Misdirected Request
nginx error log, info level (site owners)client attempted to request the server name different from the one that was negotiated

Why this happens

The connection was set up for one site, and the request asked for another.

In the TLS handshake the client names a site (SNI), and the server loads its certificate and settings, or the default site's if none is named. Apache then refuses a Host header naming a differently configured site.

Diagnose your 421 first

Start with a second device, then separate script, proxy and server causes.

  • Open the page on another device on the same Wi-Fi; if Misdirected Request shows there too, the server refuses everyone.

  • Run curl -s -o /dev/null -w '%{http_code}' on the plain URL; if it prints 200, your script's Host header or IP address URL caused it.

  • Through a proxy, add %{http_connect} to that -w; 200 421 means the tunnel opened and the website sent the 421.

  • Site owners: search Apache's error log for AH02032; the line names the hostname from SNI and the different one from Host.

  • If that line says 'default host as no SNI was provided', your front proxy connects without a server name.

Solutions ranked by effectiveness

Each fix below belongs to whoever runs the server or writes the script.

  1. Most common fix

    Make your front proxy send the hostname

    Applies when every visitor gets 421 and AH02032 mentions the default host: your front proxy connects to Apache without a name, so Apache assumes its first virtual host.

    1. In the nginx location that proxies to Apache, add proxy_ssl_server_name on;.

    2. Add proxy_ssl_name $host; so SNI carries the visitor's hostname, not the upstream's.

    3. Set proxy_set_header Host $host; so SNI and Host name the same site.

    4. Reload nginx, open each hostname and check for new AH02032 lines.

  2. Site owners

    Match TLS settings across hosts sharing a certificate

    Applies when access logs show 421s while pages still load: browsers reuse one host's connection for a sibling on the same certificate.

    1. Find virtual hosts whose certificate also lists another of your hostnames.

    2. Give each such pair one certificate and equal SSLProtocol, SSLCipherSuite and client-certificate settings.

    3. Or drop the other hostname from that certificate, so browsers stop sharing connections.

  3. For developers

    Stop overriding the Host header

    Applies when your script's URL names one site or an IP while a Host header names another. Clients take the TLS name from the URL, so SNI and Host disagree.

    1. Remove the custom Host header from the request and client defaults.

    2. Put the hostname you want in the URL, so SNI and Host match.

    3. To test one server by IP, pin it as our Cloudflare 1003 guide shows.

Stop the 421 from coming back

Habits that catch a name mismatch before visitors do.

  1. Before upgrading Apache, test requests that arrive without SNI; 2.4.64 began applying this check to them.

  2. On httpd 2.4.66 or later, keep SSLVHostSNIPolicy at its default, secure; insecure may expose CVE-2025-23048.

  3. Log SNI beside Host with %{SSL_TLS_SNI}x in your LogFormat, so mismatches show without debug logging.

  4. Alert on 421 counts in access logs; a jump right after a deploy points to a TLS or proxy change.

  5. Let your own HTTP client retry a 421 once over a separate connection; RFC 9110 permits that even for POST.

Find your own checks in logsTest from an assigned ISP IP, then filter your access log by that address.
Try ISP proxies

Related errors

Learn more

FAQ

It is Misdirected Request, a 4xx status RFC 9110 defines for a server that will not or cannot answer authoritatively for the URL. Unlike ERR_CERT_COMMON_NAME_INVALID, the certificate passed; the refusal came afterwards.

Visitors can only report it to the site's owner. Owners make the front proxy send the right SNI or align TLS settings; scripts stop overriding Host.

HTTP/2 browsers reuse an open connection for a second hostname when the certificate covers both names and DNS returns the same IP. On a 421, Chrome resends the request once on a new connection.

No. Our HTTP/1.1 request with mismatched SNI and Host got the same 421 from Apache; turning off HTTP/2 only stops browsers reusing one connection across hostnames.

nginx sends 421 when the Host header differs from the SNI name and the server block Host selects has ssl_verify_client on. Without client certificates, nginx serves that block instead.

RFC 9110 says a proxy must not, and 421 is not among the codes Geonode's docs list for its gateway. Inside an HTTPS tunnel, your client sets SNI and Host, so the website sent it.

Keep staging private while testing

Allowlist a Dedicated ISP IP, used only by you, on staging and test through it.