denoland/deno · error · TypeError
ERR_INVALID_CHAR
ERR_INVALID_CHAR
Error message
Invalid character in alt
What it means
altsvc()'s alt parameter is validated against kQuotedString, which in this file is the regex ^[\x09\x20-\x5b\x5d-\x7e\x80-\xff]*$ — tab, printable ASCII (excluding backslash 0x5c), and bytes 0x80-0xff. Any other byte, notably CR, LF, other control characters, or a backslash, throws ERR_INVALID_CHAR because the ALTSVC field value must be a single-line quoted-string per RFC 7838.
Source
Thrown at ext/node/polyfills/http2.ts:4621
// than a URL, then it is possible that origin will be malformed.
// We do not verify that here. Users who go that route need to
// ensure they are doing the right thing or the payload data will
// be invalid.
if (typeof origin !== "string") {
throw new ERR_INVALID_ARG_TYPE("originOrStream", [
"string",
"number",
"URL",
"object",
], originOrStream);
} else if (origin === "null" || origin.length === 0) {
throw new ERR_HTTP2_ALTSVC_INVALID_ORIGIN();
}
}
validateString(alt, "alt");
if (!kQuotedString.test(alt)) {
throw new ERR_INVALID_CHAR("alt");
}
// Max length permitted for ALTSVC
if (
(alt.length + (origin !== undefined ? origin.length : 0)) > kMaxALTSVC
) {
throw new ERR_HTTP2_ALTSVC_LENGTH();
}
this[kHandle].altsvc(stream, origin || "", alt);
}
// Submits an origin frame to be sent.
origin(...origins) {
if (this.destroyed) {
throw new ERR_HTTP2_INVALID_SESSION();
}
View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Keep alt a single-line value such as 'h2=":443"' or 'h2-16="alt.example.com:443"'
- Strip/validate with alt.trim() plus a control-character check before calling
- Treat embedded CR/LF in alt as an injection attempt and reject the input, not just clean it
Example fix
// before
session.altsvc(config.altSvcValue, origin); // value has trailing '\n'
// after
const alt = config.altSvcValue.trim();
if (/[\r\n\\]/.test(alt)) throw new Error('invalid alt-svc value');
session.altsvc(alt, origin); Defensive patterns
Strategy: validation
Validate before calling
if (/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f\\]/.test(alt)) {
throw new TypeError('alt must be a single-line quoted-string value');
}
session.altsvc(alt, origin); Type guard
function isValidAltValue(alt) {
return typeof alt === 'string' && /^[\t\x20-\x5b\x5d-\x7e\x80-\xff]*$/.test(alt);
} Prevention
- Treat CR/LF in alt as header injection — reject the input at your trust boundary
- Trim values loaded from config files to drop trailing newlines
- Standard values look like 'h2=":443"'; keep them short and literal
When it happens
Trigger: altsvc('h2=":443"\r\nX: 1', origin) (header-injection attempt or embedded newline); altsvc with a backslash-escaped value; a value containing a NUL or other control character copied from binary data.
Common situations: Building the alt value by string concatenation with unsanitized user input; values read from a config file that contains a trailing newline; template literals that interpolate multi-line strings.
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
- ERR_INVALID_ARG_VALUE
- ERR_INVALID_ARG_TYPE
- ERR_HTTP2_INVALID_INFO_STATUS
- ERR_OUT_OF_RANGE
- ERR_HTTP2_PING_LENGTH
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/2debc0c135c9267f.
Report an issue: GitHub.