How to fix Error: Invalid HTTP version (unsupported protocol) in Node.js
This error occurs when a Node.js HTTP client receives an HTTP response with a version string that the parser cannot recognize or does not support. It typically indicates a protocol mismatch, malformed server response, or incompatibility with an intermediary like a proxy or load balancer.
Quick fix
Fixes Error: Invalid HTTP version (unsupported protocol)
# Test HTTP/1.1 (default)
curl -v http://example.com
# Test HTTP/2
curl --http2 -v https://example.com
# Test HTTP/3 (QUIC)
curl --http3 -v https://example.com
# Check response headers and protocol version
curl -i http://example.com | head -20- Verify the HTTP version expected by the server
- Check your Node.js HTTP client configuration
- Disable HTTP/2 support if encountering proxy issues
- Check proxy and load balancer configuration
# Test HTTP/1.1 (default)curl -v http://example.com# Test HTTP/2curl --http2 -v https://example.com# Test HTTP/3 (QUIC)curl --http3 -v https://example.com# Check response headers and protocol versioncurl -i http://example.com | head -20Error: Invalid HTTP version (unsupported protocol)
What this error means
The "Invalid HTTP version" error is raised when Node.js's HTTP parser encounters an unrecognized HTTP version string in a server response or request line. The HTTP specification defines valid versions like HTTP/1.0, HTTP/1.1, HTTP/2, and HTTP/3, but servers or proxies may return malformed versions like "HTTP/2.0" (invalid), "HTTP/1" (incomplete), or corrupted version strings. Node.js validates HTTP versions strictly during parsing. When the parser encounters a version it cannot understand or that doesn't conform to the HTTP specification, it throws this error to prevent processing a potentially malicious or corrupted message. This error is distinct from protocol mismatch errors (using http:// with an HTTPS endpoint) and usually indicates either a server configuration issue, proxy misconfiguration, or data corruption during transmission. It often surfaces in proxy environments, CDN requests, or connections through middleware that may rewrite HTTP headers.
Typical symptoms
- HTTP requests fail with "Error: Invalid HTTP version (unsupported protocol)"
- Requests work when accessing the server directly but fail through a proxy
- Only specific endpoints or request types trigger the error
- Error occurs intermittently or only with certain HTTP versions
- Works in development but fails when deploying through a load balancer or CDN
- Upstream proxy server is returning malformed HTTP responses
- Mixed use of HTTP and HTTPS in request chains causes parsing failures
Common causes
- Server or proxy returning malformed HTTP version strings (e.g., "HTTP/2.0" instead of "HTTP/2")
- Protocol mismatch between client expectation and server response
- Proxy or load balancer injecting or rewriting invalid HTTP headers
- Network corruption or incomplete HTTP response transmission
- Node.js HTTP client library attempting to use an unsupported HTTP version
- Misconfigured reverse proxy (nginx, Apache, HAProxy) returning invalid headers
- SSL/TLS proxy or man-in-the-middle device corrupting HTTP headers
- Legacy or custom HTTP server implementation returning non-standard version strings
How to fix "Error: Invalid HTTP version (unsupported protocol)"
Check what HTTP version your target server supports using curl or other tools:
# Test HTTP/1.1 (default)
curl -v http://example.com
# Test HTTP/2
curl --http2 -v https://example.com
# Test HTTP/3 (QUIC)
curl --http3 -v https://example.com
# Check response headers and protocol version
curl -i http://example.com | head -20The first line of the response should show a valid HTTP version like "HTTP/1.1 200 OK" or "HTTP/2 200". If you see an invalid format, the server is misconfigured.
Verify that your Node.js code is using compatible HTTP versions:
const http = require('http');
const https = require('https');
// Standard HTTP/1.1 request (default)
const req = https.get('https://example.com', (res) => {
console.log(`Protocol: ${res.httpVersion}`); // Should be "1.1" or "2.0"
res.pipe(process.stdout);
});
req.on('error', (err) => {
console.error('Request error:', err.message);
});Ensure you're using http for HTTP URLs and https for HTTPS URLs. Mixing protocols causes parsing issues.
If the error occurs when routing through a proxy, try disabling HTTP/2:
const https = require('https');
const options = {
hostname: 'example.com',
port: 443,
path: '/',
method: 'GET',
// Disable HTTP/2 for compatibility with some proxies
http2: false,
};
const req = https.request(options, (res) => {
console.log(`Status: ${res.statusCode}`);
res.on('data', (chunk) => {
process.stdout.write(chunk);
});
});
req.on('error', (err) => {
console.error('Request error:', err.message);
});
req.end();Some older proxies don't properly handle HTTP/2, causing them to return malformed version strings.
If requests fail when routing through a proxy, review the proxy settings:
For nginx reverse proxy, ensure valid HTTP version handling:
upstream backend {
server backend-server:3000;
# Ensure proxy passes valid HTTP versions
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
# Explicitly set HTTP version
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}Check that the proxy is not rewriting or corrupting the HTTP version header.
HTTP parsing in Node.js improves with each version. Update to the latest LTS or current version:
# Check current Node.js version
node --version
# Update Node.js using nvm (recommended)
nvm install --lts
nvm use --lts
# Or update via your package manager
# macOS
brew upgrade node
# Ubuntu/Debian
sudo apt update && sudo apt upgrade nodejs
# Verify update
node --versionNewer versions have better error handling and compatibility with various proxy configurations.
Handle this error gracefully and retry with different HTTP versions:
const https = require('https');
async function fetchWithFallback(url, options = {}) {
const httpVersions = ['1.1', '1.0']; // Fallback sequence
for (const version of httpVersions) {
try {
console.log(`Attempting with HTTP/${version}...`);
const opts = {
...options,
http2: version !== '1.0' && version !== '1.1',
};
return await new Promise((resolve, reject) => {
https.get(url, opts, (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => resolve(data));
}).on('error', reject);
});
} catch (err) {
console.error(`Failed with HTTP/${version}: ${err.message}`);
if (version === httpVersions[httpVersions.length - 1]) {
throw err; // All versions failed
}
}
}
}
fetchWithFallback('https://example.com')
.then((data) => console.log('Success:', data))
.catch((err) => console.error('All attempts failed:', err.message));This approach automatically retries with different HTTP versions if the server is misconfigured.
Use network debugging tools to see the exact HTTP version being returned:
# Capture HTTP traffic with tcpdump
sudo tcpdump -i any -A 'tcp port 443 or tcp port 80' | grep -i 'HTTP'
# Or use Wireshark for GUI packet inspection
wireshark
# Use curl with maximum verbosity
curl -vvv http://example.com 2>&1 | head -40
# Check for Node.js HTTP debug logs
NODE_DEBUG=http node your-script.js 2>&1 | head -50Look for the exact response line. Valid responses should look like:
- HTTP/1.1 200 OK
- HTTP/2 200
- HTTP/1.0 200 OK
Invalid responses might show corrupted version strings like HTTP/2.0 or HTTP without a version.
Advanced notes
Understanding HTTP Version Parsing in Node.js
Node.js uses the llhttp library (successor to http-parser) for HTTP parsing. The parser strictly validates HTTP versions against the HTTP specification. Valid versions include:
- HTTP/1.0 (deprecated but still supported)
- HTTP/1.1 (most common)
- HTTP/2 (or h2)
- HTTP/3 (QUIC, newer)
The parser rejects anything that doesn't match the pattern, including:
- HTTP/2.0 (should be HTTP/2)
- HTTP/1 (incomplete, needs .0 or .1)
- HTTPS/1.1 (HTTPS is a protocol, not a version)
- h2c (HTTP/2 Cleartext) over non-encrypted connections may also cause issues
Proxy-Specific Issues
Corporate proxies, especially older ones or those with SSL inspection, may:
- Rewrite HTTP version headers
- Return malformed upgrade responses
- Fail to properly translate between HTTP versions
- Inject custom headers that break parsing
Solutions:
1. Bypass the proxy if possible for specific requests
2. Configure the proxy to use HTTP/1.1 exclusively
3. Use a proxy authentication library if credentials are needed
4. Contact proxy administrator to update configuration
TLS/SSL Interception Problems
Some security appliances intercept HTTPS traffic and re-encrypt it, potentially corrupting HTTP version information. If the error only occurs with HTTPS:
// Allow self-signed certificates from intercepting proxy (development only)
const https = require('https');
const agent = new https.Agent({
rejectUnauthorized: false, // WARNING: For testing only!
});
https.get('https://example.com', { agent }, (res) => {
console.log('Success');
});In production, work with your security team to configure proper certificate chains.
HTTP/2 Server Push and Version Mismatches
If using HTTP/2 server push, ensure your client properly handles it:
const spdy = require('spdy'); // For HTTP/2 support
const req = spdy.request(options, (res) => {
res.on('push', (err, pushedRes) => {
if (err) {
console.error('Push error:', err.message);
return;
}
console.log('Received push:', pushedRes.url);
});
});Ensure both client and server negotiate the same protocol version in TLS handshake.
Load Balancer Configuration
For applications behind load balancers (AWS ELB, Google Load Balancer, etc.):
- AWS ALB: Ensure HTTP/2 is enabled if clients expect it
- Google Cloud Load Balancer: Check HTTP version settings
- Kubernetes Ingress: Verify ingress controller HTTP version support
Contact your hosting provider's support if upgrading HTTP versions on load balancers.
Frequently asked questions
- What does "Error: Invalid HTTP version (unsupported protocol)" mean?
- js's HTTP parser encounters an unrecognized HTTP version string in a server response or request line. 0" (invalid), "HTTP/1" (incomplete), or corrupted version strings. js validates HTTP versions strictly during parsing.
- How do I fix "Error: Invalid HTTP version (unsupported protocol)"?
- This error occurs when a Node.js HTTP client receives an HTTP response with a version string that the parser cannot recognize or does not support. It typically indicates a protocol mismatch, malformed server response, or incompatibility with an intermediary like a proxy or load balancer.
- What causes "Error: Invalid HTTP version (unsupported protocol)"?
- Server or proxy returning malformed HTTP version strings (e.g., "HTTP/2.0" instead of "HTTP/2") Protocol mismatch between client expectation and server response Proxy or load balancer injecting or rewriting invalid HTTP headers
- Is the "Error: Invalid HTTP version (unsupported protocol)" error serious?
- It is a medium-severity error โ more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- ๐Node.js Official Documentation
- ๐
- ๐
- ๐github.com - llhttp(GitHub)