denoland/deno · error · NodeTypeError
ERR_INVALID_CHAR
ERR_INVALID_CHAR
Error message
Invalid character in trailer content ["${field}"] What it means
While assembling trailers, addTrailers runs checkInvalidHeaderChar on each value; a value containing characters illegal in a header field value (control characters such as \r, \n, \t, other C0 controls) throws ERR_INVALID_CHAR for 'trailer content'. The check exists to prevent header/trailer injection through unsanitized values, since the trailer is serialized verbatim after the terminal chunk.
Source
Thrown at ext/node/polyfills/_http_outgoing.ts:546
value: function addTrailers(headers: any) {
this._trailer = "";
const keys = ObjectKeys(headers);
const isArray = ArrayIsArray(headers);
let field, value;
for (let i = 0, l = keys.length; i < l; i++) {
if (isArray) {
field = headers[keys[i]][0];
value = headers[keys[i]][1];
} else {
field = keys[i];
value = headers[field];
}
if (typeof field !== "string" || !field || !checkIsHttpToken(field)) {
throw new ERR_INVALID_HTTP_TOKEN("Trailer name", field);
}
if (checkInvalidHeaderChar(value)) {
debug('Trailer "%s" contains invalid characters', field);
throw new ERR_INVALID_CHAR("trailer content", field);
}
this._trailer += field + ": " + value + "\r\n";
}
},
writable: true,
enumerable: true,
configurable: true,
},
end: {
__proto__: null,
value: function end(chunk: any, encoding: any, callback: any) {
if (typeof chunk === "function") {
callback = chunk;
chunk = null;
encoding = null;
} else if (typeof encoding === "function") {
callback = encoding;
encoding = null;View on GitHub (pinned to 89f33cbef2)
Solutions
- Sanitize values: strip/encode control characters before passing to addTrailers
- Trim newline-terminated command output used as trailer values
- Encode arbitrary data (base64/hex) so only printable ASCII remains
Example fix
// before
res.addTrailers({ 'x-checksum': execSync('sha256sum f | cut -d" " -f1') }); // has trailing \n
// after
const sum = execSync('sha256sum f | cut -d" " -f1').toString().trim();
res.addTrailers({ 'x-checksum': sum }); Defensive patterns
Strategy: validation
Validate before calling
function sanitizeTrailerValue(v) {
return String(v).replace(/[\r\n\t\x00-\x1f\x7f]/g, '');
}
res.addTrailers({ 'x-checksum': sanitizeTrailerValue(sum) }); Type guard
const isCleanTrailerValue = (v) => typeof v === 'string' && !/[\r\n\t\x00-\x1f\x7f]/.test(v);
Try / catch
try { res.addTrailers(t); } catch (e) { if (e.code === 'ERR_INVALID_CHAR') { /* strip control chars and retry once */ } else throw e; } Prevention
- Trim newline-terminated tool output before use
- Encode binary/b64 for trailer values
- Treat trailer values as untrusted output; sanitize like headers
When it happens
Trigger: addTrailers({ 'x-checksum': hash + '\n' }) (newline-terminated data); values sourced from user input, logs, or external APIs containing control characters; binary buffers stringified with control bytes.
Common situations: Checksums or metadata computed by tools that append newlines (wc, openssl dg2 outputs); proxying upstream values into trailers without sanitization; injecting request data into trailer values creating a smuggling vector.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid header value: "${value}"
- ERR_INVALID_HTTP_TOKEN
- ERR_INVALID_CHAR
- Unsupported 'alpnProtocols' option provided. 'h2' and 'http/
- ERR_INVALID_ARG_TYPE
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/f28eda1d966d50f5.
Report an issue: GitHub.