HTTP 505 is HTTP Version Not Supported: the server doesn’t support, or refuses to support, the major version of HTTP used in the request (RFC 9110 section 15.6.6). It should send a body saying why, and which protocols it does support. It’s about the major version only: HTTP/1.0 and HTTP/1.1 share one, and a server answers in the highest version it supports at or below the request’s (section 6.2), so a minor version never calls for a 505.
How you get one
The version in a request line doesn’t choose HTTP/2 or HTTP/3. HTTP/2 is agreed in the TLS handshake with ALPN (h2), or spoken over cleartext by prior knowledge; HTTP/3 is found through Alt-Svc or a DNS HTTPS record and runs over QUIC. So a 505 means an HTTP/1.x server received a request line with a version it can’t speak:
- nginx answers 505 to a request line whose major version is above 1.
- Go’s server answers
505 HTTP Version Not Supported: unsupported protocol versionto any major version other than 1, except the HTTP/2 preface linePRI * HTTP/2.0, which it lets through for HTTP/2 setups. - Hand-written requests, such as a test script that sends
GET / HTTP/2.0over a plain socket.
printf 'GET / HTTP/2.0\r\nHost: example.com\r\n\r\n' | nc example.com 80
HTTP/1.1 505 HTTP Version Not Supported
That is nginx 1.27’s reply. Real cleartext HTTP/2 doesn’t get a 505 from it: curl --http2-prior-knowledge opens with the preface PRI * HTTP/2.0, which an HTTP/1.1-only nginx answers with 400 Bad Request, and curl then gives up with exit code 16, an HTTP/2 framing error, without showing either status.
505, 426 or 101
the request used a major version the server won't speak 505 HTTP Version Not Supported
the server wants the client to switch protocols first 426 Upgrade Required, with Upgrade
the server agreed to switch 101 Switching Protocols
What to do
- As a client, let the library negotiate. Over TLS, ALPN picks HTTP/2 when both sides support it, and falls back to HTTP/1.1 otherwise; nobody has to write a version by hand.
- Behind a proxy, check what the proxy speaks to the upstream. nginx talks HTTP/1.0 to proxied servers unless
proxy_http_version 1.1says otherwise, which is still the same major version and never a reason for a 505. - As a server, say in the body what you do support, as RFC 9110 asks.
Gotchas
- HTTP/0.x. Go answers 505 to a request line that claims
HTTP/0.9, too. - Caching. 505 isn’t heuristically cacheable.
- It’s a 5xx even though the client chose the version, so monitoring counts it as a server error.
Search 426 505 in the tool below to compare the two.