506 Variant Also Negotiates
Server error response defined by RFC 2295 §8.1.
Last updated July 27, 2026
Common causes at a glance
- Apache MultiViews or a type-map pointing at another negotiable resource
- A hand-written type-map file listing a variant that is itself a variant list
- A server implementing RFC 2295 with a cyclic variant configuration
- A framework reusing 506 for an unrelated internal error, which is simply wrong
Reproduce it
curl -sSI -H 'Negotiate: 1.0' https://www.example.com/docWhat 506 Variant Also Negotiates means
Transparent content negotiation was an attempt to let a client pick among
representations using a machine-readable list of variants, rather than having the server
guess from Accept headers. A negotiable resource points at a set of
concrete variants — a French HTML page, an English one, a PDF — and each variant is
supposed to be a leaf.
506 fires when a variant turns out to be another negotiable resource, which would start
the negotiation again with no guarantee of terminating. The server detects the cycle and
refuses. In practice this means someone enabled Apache MultiViews or a
type-map and pointed it at a target that is itself negotiated. This is a museum piece:
the modern web negotiates with Accept, Accept-Language, and
Vary, and you can spend a career without meeting a 506.
What the spec says
506 is defined in RFC 2295 §8.1, “Transparent Content
Negotiation in HTTP”, which is Experimental and has never advanced. The definition is
short: the server has an internal configuration error because the chosen variant
resource is configured to engage in transparent content negotiation itself and is
therefore not a proper endpoint. The surrounding document defines the
Negotiate, Alternates, and TCN header fields the
scheme depends on. The
IANA registry
still lists 506 against RFC 2295, which is why it keeps appearing in status tables
alongside codes you actually use.
What actually causes it
Apache mod_negotiation is realistically the only
implementation you might trip over. Enabling Options +MultiViews on a
directory and then adding a .var type-map whose entries resolve back into
the same negotiated space produces exactly the loop the code exists to report. The other
way to see 506 is somebody picking it out of a status list because it sounded vaguely
applicable. A service returning 506 for a validation failure or a routing error should
return 500 or an appropriate 4xx instead.
How to debug it
Confirm you are actually in a negotiation flow before investigating anything
else. A transparently negotiated response carries a TCN header and an
Alternates list:
curl -sSI -H 'Negotiate: 1.0' https://www.example.com/doc | grep -Ei 'HTTP|tcn|alternates|vary'
If neither header is present, whatever produced the 506 is not doing RFC 2295
negotiation and the code is coming from application logic — go read that code. If the
headers are there, the fix is in server configuration: find the variant named in the
Alternates list and check whether it resolves to another negotiable
resource. Disabling MultiViews and serving explicit paths removes the whole
class of problem, at no cost that Accept-based negotiation cannot cover.
Working examples
curl
# Ask for transparent negotiation explicitly and inspect the headers.
curl -sSI -H 'Negotiate: 1.0' https://www.example.com/doc \
| grep -Ei 'HTTP|tcn|alternates|vary|content-location'
# Compare with ordinary Accept-based negotiation, which is what you should use.
curl -sSI -H 'Accept-Language: fr' https://www.example.com/doc | grep -Ei 'HTTP|vary'
Python (requests)
import requests
resp = requests.get(
"https://www.example.com/doc",
headers={"Negotiate": "1.0"},
timeout=10,
)
print(resp.status_code)
print("TCN:", resp.headers.get("TCN"))
print("Alternates:", resp.headers.get("Alternates"))
if resp.status_code == 506:
# The named variant is itself negotiable: a server-side config loop.
print("nothing a client can fix here")
Node (fetch)
const res = await fetch("https://www.example.com/doc", {
headers: { Negotiate: "1.0" },
});
console.log(res.status);
console.log("tcn:", res.headers.get("tcn"));
console.log("alternates:", res.headers.get("alternates"));
if (res.status === 506) {
// The variant list points at another negotiable resource. Server-side fix only.
console.error("RFC 2295 negotiation loop on the server");
}Reference and tooling
The authoritative list of assigned status codes is theIANA HTTP Status Code Registry. For a searchable copy with the semantics summarised, use theHTTP status code reference on this site. To see exactly what a server is sending, theheader inspector shows the raw status line and response headers, and thecurl builder assembles the request flags for you.
Other 5xx codes
- 500 Internal Server Error
- 501 Not Implemented
- 502 Bad Gateway
- 503 Service Unavailable
- 504 Gateway Timeout
- 505 HTTP Version Not Supported
- 507 Insufficient Storage
- 508 Loop Detected
- 510 Not Extended
- 511 Network Authentication Required
- 520 Web Server Returns an Unknown Error
- 521 Web Server Is Down
- 522 Connection Timed Out
- 523 Origin Is Unreachable
- 524 A Timeout Occurred
- 525 SSL Handshake Failed
- 526 Invalid SSL Certificate
- 530 Unable to Resolve Origin Hostname