This error occurs when Node.js HTTP/2 session receives a SETTINGS frame that does not comply with HTTP/2 protocol specifications. The settings frame may contain invalid parameter IDs, out-of-range values, or malformed data that the HTTP/2 parser cannot process.
The "HTTP/2 invalid settings frame (malformed settings)" error occurs when Node.js attempts to process HTTP/2 SETTINGS frames that violate the HTTP/2 specification (RFC 7540). A SETTINGS frame is used by HTTP/2 to exchange connection parameters between client and server. This error can arise from several protocol violations: - Settings parameters with unknown IDs - Parameter values outside valid ranges (e.g., max frame size < 16KB or > 24MB) - Incomplete or truncated SETTINGS frames - Incorrect frame length or structure - Server sending settings with deprecated or unsupported parameter combinations The error indicates that either the remote peer is sending malformed HTTP/2 data, or there's an issue with how the connection is being negotiated.
Enable Node.js HTTP/2 debugging to see detailed frame information:
# On Linux/macOS
NODE_DEBUG=http2 node your-app.js
# On Windows (PowerShell)
$env:NODE_DEBUG='http2'
node your-app.jsThis will output detailed logs showing the exact SETTINGS frame content and which parameter is invalid.
Test the HTTP/2 server with standard tools:
# Using curl to test HTTP/2 server
curl -I --http2 https://example.com/
# Using h2spec to validate HTTP/2 compliance
go install github.com/summerwind/h2spec/v2@latest
h2spec -port 443 -tls example.comIf the server fails h2spec tests, it has HTTP/2 compliance issues that need to be fixed on the server side.
HTTP/2 proxies or CDNs may incorrectly transform settings frames. Test direct connection:
# Try connecting directly to the origin IP (if accessible)
dig +short example.com # Get the IP
curl -I --http2 --connect-to example.com:443:x.x.x.x:443 https://example.com/
# Or bypass proxies by connecting to the host directly
telnet example.com 443If direct connection works but proxied connection fails, the intermediary is corrupting HTTP/2 frames.
Ensure you have the latest Node.js version with HTTP/2 patches:
# Check current version
node --version
# Update to the latest stable version (using nvm)
nvm install --latest-npm node
nvm use node
# Or update manually from https://nodejs.org/HTTP/2 protocol support improves with each Node.js release. Older versions may have stricter or less correct validation.
Configure your HTTP/2 client with conservative settings:
const http2 = require('http2');
// Create HTTP/2 session with explicit settings
const session = http2.connect('https://example.com/', {
settings: {
headerTableSize: 4096,
enablePush: false,
initialWindowSize: 65535,
maxFrameSize: 16384, // Use minimum allowed value
maxConcurrentStreams: 100,
maxHeaderListSize: 8192
}
});
session.on('error', (err) => {
console.error('Session error:', err.message);
});
session.on('remoteSettings', (settings) => {
console.log('Received settings from server:', settings);
});Start with conservative values and the error persists, the issue is on the server side.
Add proper error handling for HTTP/2 failures:
const http2 = require('http2');
async function makeRequest() {
return new Promise((resolve, reject) => {
const session = http2.connect('https://example.com/');
session.once('error', (err) => {
console.error('HTTP/2 error:', err.message);
// If it's a settings frame error, log details
if (err.message.includes('settings frame')) {
console.error('Server sent invalid HTTP/2 settings');
console.error('Consider contacting the API provider');
}
reject(err);
});
const req = session.request({ ':path': '/api/data' });
req.on('response', (headers) => {
resolve(headers);
session.close();
});
req.end();
});
}
makeRequest().catch(err => {
console.error('Request failed:', err.message);
});If the issue persists and the remote server cannot be changed, contact the API provider:
1. Provide the exact error message and Node.js version
2. Include the NODE_DEBUG=http2 output showing the invalid settings
3. Share the results from h2spec testing
4. Request they review their HTTP/2 implementation
Example message:
I'm getting "HTTP/2 invalid settings frame (malformed settings)" when connecting
from Node.js v{version}. The connection fails immediately during the settings
negotiation phase. Testing with h2spec shows [list issues found]. Can you review
your HTTP/2 settings frame implementation against RFC 7540?HTTP/2 SETTINGS Frame Structure:
Each SETTINGS frame contains zero or more settings, each as a parameter ID (2 bytes) + value (4 bytes). Valid parameter IDs per RFC 7540:
- 0x0001: HEADER_TABLE_SIZE (0 to 2^32-1)
- 0x0002: ENABLE_PUSH (0 or 1 only)
- 0x0003: MAX_CONCURRENT_STREAMS (0 to 2^32-1)
- 0x0004: INITIAL_WINDOW_SIZE (0 to 2^31-1)
- 0x0005: MAX_FRAME_SIZE (16384 to 2^24-1)
- 0x0006: MAX_HEADER_LIST_SIZE (0 to 2^32-1)
Any other parameter ID or out-of-range value triggers this error.
Common Server-Side Issues:
1. Reverse proxy misconfiguration: nginx/Apache HTTP/2 settings may be incorrectly passed to upstream
2. Node.js version mismatch: Some HTTP/2 servers have bugs with specific Node.js versions
3. TLS/ALPN negotiation issues: Server may offer HTTP/2 but implementation is incomplete
4. Memory constraints: Some servers corrupt SETTINGS when under load
Debugging Steps:
Use Wireshark to capture the actual HTTP/2 frames:
# Capture HTTP/2 traffic
tcpdump -i eth0 -w http2.pcap 'tcp port 443'
# Or use mitmproxy to intercept and inspect HTTP/2
mitmproxy --mode reverse:https://example.com --http2 -p 8443Frame inspection will show the exact bytes causing the error.
When to Blame the Server:
This error is almost always a server-side bug. The Node.js HTTP/2 implementation is mature and RFC-compliant. If h2spec fails or you see this error consistently, the remote server needs fixing. Don't just increase timeouts or disable validation—that masks a real protocol violation.
Error: Listener already called (once event already fired)
EventEmitter listener already called with once()
Error: EACCES: permission denied, open '/root/file.txt'
EACCES: permission denied
Error: Invalid encoding specified (stream encoding not supported)
How to fix Invalid encoding error in Node.js readable streams
Error: EINVAL: invalid argument, open
EINVAL: invalid argument, open
TypeError: readableLength must be a positive integer (stream config)
TypeError: readableLength must be a positive integer in Node.js streams