denoland/deno · error · NodeTypeError

ERR_INVALID_HTTP_TOKEN

ERR_INVALID_HTTP_TOKEN

Error message

Method must be a valid HTTP token ["${method}"]

What it means

After confirming options.method is a non-empty string, ClientRequest runs checkIsHttpToken on it. Methods must be a valid HTTP token (RFC 7230 tchar: alphanumerics and !#$%&'*+-.^_`|~). A string containing spaces, slashes, newlines, or other delimiters throws ERR_INVALID_HTTP_TOKEN. Valid methods are then uppercased and stored.

Source

Thrown at ext/node/polyfills/_http_client.js:614

  if (options.timeout !== undefined) {
    this.timeout = getTimerDuration(options.timeout, "timeout");
  }

  const signal = options.signal;
  if (signal) {
    addAbortSignal(signal, this);
    delete optsWithoutSignal.signal;
  }
  let method = options.method;
  if (method != null) {
    if (typeof method !== "string") {
      throw new ERR_INVALID_ARG_TYPE("options.method", "string", method);
    }
  }

  if (method) {
    if (!checkIsHttpToken(method)) {
      throw new ERR_INVALID_HTTP_TOKEN("Method", method);
    }
    method = this.method = StringPrototypeToUpperCase(method);
  } else {
    method = this.method = "GET";
  }

  const maxHeaderSize = options.maxHeaderSize;
  if (maxHeaderSize !== undefined) {
    validateInteger(maxHeaderSize, "maxHeaderSize", 0);
  }
  this.maxHeaderSize = maxHeaderSize;

  const insecureHTTPParser = options.insecureHTTPParser;
  if (insecureHTTPParser !== undefined) {
    validateBoolean(insecureHTTPParser, "options.insecureHTTPParser");
  }
  this.insecureHTTPParser = insecureHTTPParser;

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Pass only the verb: extract tokens[0] when parsing a request line
  2. Trim and validate against the token charset before the call: /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/
  3. Reject or map unknown custom methods to a safe verb instead of forwarding raw strings

Example fix

// before
const method = rawLine; // 'GET /index HTTP/1.1'
const req = http.request({ host, method });

// after
const method = rawLine.split(' ')[0].trim();
const req = http.request({ host, method });
Defensive patterns

Strategy: validation

Validate before calling

const HTTP_TOKEN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
if (method && !HTTP_TOKEN.test(method)) {
  throw new Error(`invalid HTTP method: ${JSON.stringify(method)}`);
}
http.request({ host, method });

Type guard

const isHttpToken = (s) => typeof s === 'string' && s.length > 0 && /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(s);

Try / catch

try { http.request({ method }); } catch (e) { if (e.code === 'ERR_INVALID_HTTP_TOKEN') { /* sanitize: method = method.trim().split(' ')[0] */ } else throw e; }

Prevention

When it happens

Trigger: Passing a whole request line as the method: { method: 'GET /x HTTP/1.1' }; method: 'get\n' from unsanitized input; custom verbs with invalid characters like 'FETCH+' or 'my method'.

Common situations: Splitting raw HTTP text manually and grabbing the wrong token; log or config lines with trailing whitespace/newlines used as method; WebDAV-style custom verbs constructed from user input without sanitization.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/764738baee9eda0d. Report an issue: GitHub.