HTTP

506 - Variant Also Negotiates

Getting a 506 Variant Also Negotiates means the server has a configuration error where a variant resource is trying to negotiate its own content, creating a negotiation loop. This server-side error (5xx) indicates an internal server misconfiguration, not a client problem. Most common when content negotiation is misconfigured, but also appears when variant resources are set up incorrectly, negotiation loops occur, or server configuration conflicts create recursive negotiation.

#Common Causes

  • Frontend: Client can't fix 506s directly—this is a server configuration issue. Requests trigger server's negotiation loop. Content negotiation headers may expose the issue.
  • Backend: Server content negotiation misconfigured. Variant resource tries to negotiate itself. Negotiation loop detected. Server configuration conflict. Content negotiation middleware error.
  • Infrastructure: Web server content negotiation misconfiguration. Reverse proxy negotiation conflicts. CDN variant handling errors.

Solutions

  1. 1Step 1: Diagnose - Check DevTools Network tab—506 responses indicate server misconfiguration. Review Accept headers sent. Check if content negotiation is involved.
  2. 2Step 2: Diagnose - Server logs show negotiation loop details. Review content negotiation configuration. Check variant resource setup. Examine server configuration files.
  3. 3Step 3: Fix - Client-side: Simplify Accept headers to avoid triggering negotiation. Use specific content types. Retry with simpler headers.
  4. 4Step 4: Fix - Server-side: Fix content negotiation configuration. Remove recursive variant negotiation. Configure variants properly. Test negotiation logic.
  5. 5Step 5: Fix - Infrastructure: Review web server negotiation settings. Fix reverse proxy configuration. Update CDN variant handling.

</>Code Examples

Fetch API: Handle 506 with Simplified Headers
1// Client-side: Handle 506 by simplifying content negotiation
2async function fetchResourceWithFallback() {
3  // Try with full content negotiation first
4  let response = await fetch('/api/resource', {
5    headers: {
6      'Accept': 'application/json, application/xml;q=0.9',
7      'Accept-Language': 'en-US, en;q=0.9',
8      'Accept-Encoding': 'gzip, deflate',
9    },
10  });
11  
12  if (response.status === 506) {
13    console.warn('Variant negotiation error - server misconfiguration detected');
14    
15    // Fallback to simpler Accept header (no variants)
16    response = await fetch('/api/resource', {
17      headers: {
18        'Accept': 'application/json', // Single format, no negotiation
19      },
20    });
21    
22    if (response.status === 506) {
23      // Last resort - accept anything (no negotiation)
24      response = await fetch('/api/resource', {
25        headers: {
26          'Accept': '*/*',
27        },
28      });
29    }
30  }
31  
32  return response.json();
33}
34
35// Avoid triggering negotiation loops
36async function fetchResourceSimple(url) {
37  // Use simple Accept header to avoid negotiation issues
38  const response = await fetch(url, {
39    headers: {
40      'Accept': 'application/json', // Single format
41    },
42  });
43  
44  if (response.status === 506) {
45    throw new Error('Server configuration error: variant negotiation loop');
46  }
47  
48  return response.json();
49}
Express.js: Fix Content Negotiation Configuration
1// Server-side: Fix content negotiation to prevent 506
2const express = require('express');
3const app = express();
4
5// BAD: This causes 506 - variant tries to negotiate itself
6app.get('/api/resource', (req, res) => {
7  const acceptHeader = req.headers.accept;
8  
9  // Don't create variants that negotiate themselves
10  // Variant resources should return content directly, not negotiate
11  
12  // GOOD: Return content directly based on Accept header
13  if (acceptHeader.includes('application/json')) {
14    res.json({ data: 'content' });
15  } else if (acceptHeader.includes('application/xml')) {
16    res.set('Content-Type', 'application/xml');
17    res.send('<data>content</data>');
18  } else {
19    // Default to JSON
20    res.json({ data: 'content' });
21  }
22});
23
24// Prevent negotiation loops
25const preventNegotiationLoop = (req, res, next) => {
26  // Check if we're already in a negotiation context
27  if (req.headers['x-negotiation-depth']) {
28    const depth = parseInt(req.headers['x-negotiation-depth']);
29    if (depth > 1) {
30      return res.status(506).json({
31        error: 'Variant Also Negotiates',
32        message: 'Content negotiation loop detected',
33      });
34    }
35  }
36  
37  // Add depth tracking
38  req.headers['x-negotiation-depth'] = 
39    (parseInt(req.headers['x-negotiation-depth'] || '0') + 1).toString();
40  
41  next();
42};
43
44// Apply to negotiation endpoints
45app.use('/api/variants', preventNegotiationLoop);
Nginx: Fix Content Negotiation
1# Nginx: Configure content negotiation properly to prevent 506
2server {
3    listen 80;
4    server_name api.example.com;
5    
6    # Enable content negotiation
7    location /api/resources/ {
8        # Don't create recursive negotiation
9        # Variants should be static files, not dynamic negotiation
10        
11        # Serve JSON by default
12        try_files $uri.json $uri/index.json =404;
13        
14        # Or proxy to backend (backend handles negotiation)
15        proxy_pass http://backend;
16        proxy_set_header Host $host;
17        proxy_set_header Accept $http_accept;
18        
19        # Backend should not create variants that negotiate
20    }
21    
22    # Avoid variant negotiation loops
23    # Don't configure variants that point to other variants
24}

Related Errors

Provider Information

This error code is specific to HTTP services. For more information, refer to the official HTTP documentation.

506 - Variant Also Negotiates | HTTP Error Reference | Error Code Reference