This error occurs when a Node.js application attempts to communicate with a server using an outdated or unsupported protocol version. The server responds with HTTP 426, indicating the client must upgrade to a newer protocol (such as HTTPS, HTTP/2, or a specific TLS version) before the request can be processed.
The HTTP 426 Upgrade Required status code signals that the server is refusing to perform a request because the client is using an incompatible or obsolete protocol. The server will not process the request using the current protocol but indicates it would accept the same request if the client upgrades to a different protocol. In Node.js, this error typically occurs in three scenarios: attempting insecure HTTP connections to HTTPS-only servers, using outdated TLS versions (TLS 1.0 or 1.1) when the server requires TLS 1.2+, or negotiating unsupported HTTP/2 or WebSocket protocol versions. This is not a bug in Node.js itself, but a valid server response indicating a configuration or capability mismatch. The fix requires updating the client connection parameters to match what the server expects.
The most common cause is attempting to connect to an HTTPS-only server via HTTP. Update your connection URLs:
// WRONG - using HTTP
const http = require('http');
http.get('http://api.example.com/data', (res) => {
console.log(res.statusCode); // 426 Upgrade Required
});
// CORRECT - using HTTPS
const https = require('https');
https.get('https://api.example.com/data', (res) => {
console.log(res.statusCode); // 200 OK
});Or with fetch:
// WRONG
fetch('http://api.example.com/data');
// CORRECT
fetch('https://api.example.com/data');Check your configuration files and environment variables to ensure all service URLs use HTTPS.
Configure Node.js to use modern TLS versions by setting the appropriate options:
const https = require('https');
const options = {
hostname: 'api.example.com',
port: 443,
path: '/data',
method: 'GET',
minVersion: 'TLSv1.2', // Require at least TLS 1.2
};
const req = https.request(options, (res) => {
console.log(`Status: ${res.statusCode}`);
});
req.on('error', (error) => {
if (error.code === 'ERR_SSL_VERSION') {
console.log('Server requires TLS 1.2 or higher');
}
});
req.end();Or with fetch/axios:
const https = require('https');
const agent = new https.Agent({
minVersion: 'TLSv1.2',
maxVersion: 'TLSv1.3',
});
fetch('https://api.example.com/data', { agent });You can also set the NODE_OPTIONS environment variable:
export NODE_OPTIONS="--tls-min-v1.2"
npm startOlder Node.js versions may not support the TLS or HTTP/2 protocols required by modern servers. Upgrade to the latest LTS version:
# Check current version
node --version
# Using nvm (recommended)
nvm install 20 # Latest LTS
nvm use 20
# Or download from nodejs.org
https://nodejs.org/After upgrading, clear your npm cache:
npm cache clean --forceThis ensures your Node.js environment supports the latest protocol standards expected by servers.
If you encounter 426 errors with npm, update the npm registry configuration:
# Use HTTPS registry (default)
npm config set registry https://registry.npmjs.org/
# Verify the registry setting
npm config get registry
# For private registries, ensure they use HTTPS
npm config set @scope:registry https://private-registry.example.com/Clear npm cache:
npm cache clean --forceAlso update certificate handling if needed:
# Disable strict SSL if behind corporate proxy (use with caution)
npm config set strict-ssl false
# Or set a custom CA certificate
npm config set cafile /path/to/certificate.pemSome servers require HTTP/2. Ensure your Node.js client can handle protocol upgrades:
const https = require('https');
const spdy = require('spdy'); // npm install spdy
const agent = new spdy.Agent({
protocols: ['h2', 'http/1.1'],
rejectUnauthorized: false, // Only if testing - use with caution
});
https.get('https://api.example.com/data', { agent }, (res) => {
console.log('Protocol:', res.httpVersion);
res.on('data', (d) => process.stdout.write(d));
});Or use fetch with proper headers:
fetch('https://api.example.com/data', {
headers: {
'Upgrade': 'h2c',
'Connection': 'Upgrade',
}
});If using a corporate proxy or load balancer, configure it to forward upgrade headers:
const https = require('https');
const HttpProxyAgent = require('http-proxy-agent');
const HttpsProxyAgent = require('https-proxy-agent');
const httpAgent = new HttpProxyAgent('http://proxy.example.com:8080');
const httpsAgent = new HttpsProxyAgent('https://proxy.example.com:8080');
const options = {
hostname: 'api.example.com',
port: 443,
httpAgent,
httpsAgent,
headers: {
'Connection': 'upgrade',
'Upgrade': 'h2c', // Request HTTP/2 over cleartext
},
};
https.get(options, (res) => {
console.log(res.statusCode);
});For NGINX proxies, ensure Upgrade headers are passed:
location /api {
proxy_pass https://backend:443;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}Understanding the HTTP 426 Response
When you receive a 426 Upgrade Required response, the server includes an Upgrade header indicating supported protocols:
HTTP/1.1 426 Upgrade Required
Upgrade: h2, h2c, http/1.1
Connection: UpgradeParse this header to determine what protocols the server supports.
WebSocket Protocol Negotiations
For WebSocket connections, 426 indicates the server doesn't support the requested WebSocket version. Always include proper headers:
const net = require('net');
const socket = net.createConnection({
host: 'api.example.com',
port: 443,
rejectUnauthorized: true,
});
socket.write('GET /chat HTTP/1.1
');
socket.write('Host: api.example.com
');
socket.write('Upgrade: websocket
');
socket.write('Connection: Upgrade
');
socket.write('Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
');
socket.write('Sec-WebSocket-Version: 13
');
socket.write('
');Debugging Protocol Issues
Use curl or openssl to test protocol support:
# Test HTTPS and TLS version
curl -v --tlsv1.2 https://api.example.com/data
# Test HTTP/2 support
curl -v --http2 https://api.example.com/data
# Test from Node.js with debug output
NODE_DEBUG=http,https node app.jsCorporate Network and Certificates
Behind a corporate proxy with custom CA certificates:
const fs = require('fs');
const https = require('https');
const ca = fs.readFileSync('/path/to/corporate-ca.pem');
const agent = new https.Agent({
ca: ca,
minVersion: 'TLSv1.2',
});
https.get('https://api.example.com', { agent }, (res) => {
console.log(res.statusCode);
});Important Considerations
- The 426 status is correct server behavior - never work around it by downgrading protocols
- Always use HTTPS in production, never disable strict SSL in production code
- Keep Node.js updated to support the latest TLS and HTTP versions
- Monitor server upgrade header changes to stay compatible
- Use environment-specific configurations for different network setups
- 426 errors are often a sign to update infrastructure, not suppress them
Error: EMFILE: too many open files, watch
EMFILE: fs.watch() limit exceeded
Error: Middleware next() called multiple times (next() invoked twice)
Express middleware next() called multiple times
Error: Worker failed to initialize (worker startup error)
Worker failed to initialize in Node.js
Error: EMFILE: too many open files, open 'file.txt'
EMFILE: too many open files
Error: cluster.fork() failed (cannot create child process)
cluster.fork() failed - Cannot create child process