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

  1. Keep alt a single-line value such as 'h2=":443"' or 'h2-16="alt.example.com:443"'
  2. Strip/validate with alt.trim() plus a control-character check before calling
  3. 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

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

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/2debc0c135c9267f. Report an issue: GitHub.