This error occurs when attempting to set HTTP headers with invalid characters, such as control characters, newlines, or improperly encoded non-ASCII text. Node.js enforces strict HTTP header validation to prevent security vulnerabilities.
This TypeError is thrown by Node.js when you try to set an HTTP header (using `res.setHeader()`, `req.setHeader()`, or similar methods) with a value that contains characters not allowed by the HTTP specification. Node.js implements strict header validation to comply with HTTP/1.1 standards and prevent security issues like HTTP response splitting attacks. Invalid characters include control characters (like newlines \n, carriage returns \r, tabs \t), null bytes, and other non-printable characters. The error can occur in two scenarios: when setting headers in your own server/client code, or when receiving responses from remote servers that don't comply with HTTP specifications. Node.js's HTTP parser is stricter than web browsers, which helps maintain security but can cause issues when interacting with non-compliant servers.
Add logging to identify which header is causing the error:
// Log all headers before setting them
const headerValue = getHeaderValue();
console.log('Setting header:', { name: 'X-Custom-Header', value: headerValue });
console.log('Value bytes:', Buffer.from(headerValue).toString('hex'));
try {
res.setHeader('X-Custom-Header', headerValue);
} catch (err) {
console.error('Failed to set header:', err.message);
console.error('Problematic value:', JSON.stringify(headerValue));
}This will help you see the exact value and any hidden control characters.
Use Node.js's built-in validation or create a sanitization function:
const http = require('http');
// Use Node.js validation (Node 14+)
function validateHeaderValue(value) {
try {
http.validateHeaderValue('test-header', value);
return true;
} catch (err) {
return false;
}
}
// Or create custom sanitization
function sanitizeHeaderValue(value) {
if (!value) return '';
return String(value)
.replace(/[\r\n\t]/g, '') // Remove control characters
.replace(/[^\x20-\x7E]/g, '') // Keep only printable ASCII
.trim();
}
// Use it
const userInput = req.query.customValue;
const safeValue = sanitizeHeaderValue(userInput);
if (validateHeaderValue(safeValue)) {
res.setHeader('X-Custom-Header', safeValue);
}Strip newlines, carriage returns, and other control characters:
function cleanHeaderValue(value) {
if (typeof value !== 'string') {
value = String(value);
}
// Remove all control characters (ASCII 0-31 and 127)
return value.replace(/[\x00-\x1F\x7F]/g, '');
}
// Example usage
const description = req.body.description; // May contain newlines
res.setHeader('X-Description', cleanHeaderValue(description));For JSON or complex data, encode it properly:
const metadata = { user: 'John', role: 'admin\nroot' };
const encoded = Buffer.from(JSON.stringify(metadata)).toString('base64');
res.setHeader('X-Metadata', encoded);Check for empty values before setting headers:
function setHeaderSafely(res, name, value) {
// Only set header if value exists and is non-empty
if (value !== undefined && value !== null && value !== '') {
const stringValue = String(value);
if (stringValue.trim()) {
res.setHeader(name, stringValue.trim());
}
}
}
// Usage
setHeaderSafely(res, 'X-User-Id', userId);
setHeaderSafely(res, 'X-Session-Token', sessionToken);If you're making requests to a server that sends invalid headers and you can't fix the server, use the insecureHTTPParser option (use with caution):
const http = require('http');
const https = require('https');
// For http.request
const req = http.request({
hostname: 'example.com',
path: '/api',
insecureHTTPParser: true // Allows non-compliant headers
}, (res) => {
console.log('Response received:', res.statusCode);
});
// For axios
const axios = require('axios');
const axiosInstance = axios.create({
httpAgent: new http.Agent({ insecureHTTPParser: true }),
httpsAgent: new https.Agent({ insecureHTTPParser: true })
});
// For fetch with custom agent (Node 18+)
const agent = new https.Agent({ insecureHTTPParser: true });
const response = await fetch('https://example.com/api', { agent });Warning: Only use this when dealing with external servers you don't control. Never use this for your own server responses.
If you need to include non-ASCII characters in headers:
// Use RFC 2047 encoding for header values with non-ASCII
function encodeHeaderValue(value) {
// Check if value contains non-ASCII
if (/[^\x00-\x7F]/.test(value)) {
// Use base64 encoding
return '=?UTF-8?B?' + Buffer.from(value, 'utf-8').toString('base64') + '?=';
}
return value;
}
const filename = 'report_André_2025.pdf';
res.setHeader('Content-Disposition', `attachment; filename="${encodeHeaderValue(filename)}"`);
// Or use percent-encoding for URLs
const encodedFilename = encodeURIComponent(filename);
res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodedFilename}`);Error Codes: This error may be reported with different error codes depending on the exact issue:
- ERR_HTTP_INVALID_HEADER_VALUE: Invalid characters in header value
- ERR_INVALID_CHAR: Invalid character detected during header parsing
- HPE_INVALID_HEADER_TOKEN: HTTP parser detected invalid header token
HTTP Specification: According to RFC 7230, HTTP header field values consist of either visible ASCII characters (0x21-0x7E), spaces (0x20), or horizontal tabs (0x09). Control characters and other bytes outside this range are not allowed.
Security Implications: Node.js's strict validation prevents HTTP response splitting attacks, where an attacker injects newlines into headers to create additional HTTP responses. Always sanitize user input before including it in headers.
Performance: Use http.validateHeaderValue() (available since Node.js 14.18.0) sparingly in production as it adds overhead. Validate during development and sanitize at input boundaries instead.
Common Header Issues:
- Content-Disposition: Filenames with special characters or non-ASCII must be properly encoded
- Authorization: Tokens containing invalid base64 padding or control characters
- Custom headers: User-generated values like tracking IDs or metadata without sanitization
- Cookies: Values with unescaped semicolons, commas, or spaces
Debugging with curl: Test your endpoints with curl to see raw headers:
curl -v http://localhost:3000/api/endpointCompatibility: The insecureHTTPParser option was added in Node.js 12.0.0. For older versions, you may need to upgrade or use a different HTTP client library.
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