{"record":{"id":"764738baee9eda0d","repo":"denoland/deno","slug":"err-invalid-http-token","errorCode":"ERR_INVALID_HTTP_TOKEN","errorMessage":"Method must be a valid HTTP token [\"${method}\"]","messagePattern":"Method must be a valid HTTP token \\[\"(.+?)\"\\]","errorType":"validation","errorClass":"NodeTypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/_http_client.js","lineNumber":614,"sourceCode":"  if (options.timeout !== undefined) {\n    this.timeout = getTimerDuration(options.timeout, \"timeout\");\n  }\n\n  const signal = options.signal;\n  if (signal) {\n    addAbortSignal(signal, this);\n    delete optsWithoutSignal.signal;\n  }\n  let method = options.method;\n  if (method != null) {\n    if (typeof method !== \"string\") {\n      throw new ERR_INVALID_ARG_TYPE(\"options.method\", \"string\", method);\n    }\n  }\n\n  if (method) {\n    if (!checkIsHttpToken(method)) {\n      throw new ERR_INVALID_HTTP_TOKEN(\"Method\", method);\n    }\n    method = this.method = StringPrototypeToUpperCase(method);\n  } else {\n    method = this.method = \"GET\";\n  }\n\n  const maxHeaderSize = options.maxHeaderSize;\n  if (maxHeaderSize !== undefined) {\n    validateInteger(maxHeaderSize, \"maxHeaderSize\", 0);\n  }\n  this.maxHeaderSize = maxHeaderSize;\n\n  const insecureHTTPParser = options.insecureHTTPParser;\n  if (insecureHTTPParser !== undefined) {\n    validateBoolean(insecureHTTPParser, \"options.insecureHTTPParser\");\n  }\n  this.insecureHTTPParser = insecureHTTPParser;\n","sourceCodeStart":596,"sourceCodeEnd":632,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/node/polyfills/_http_client.js#L596-L632","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","solutions":["Pass only the verb: extract tokens[0] when parsing a request line","Trim and validate against the token charset before the call: /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/","Reject or map unknown custom methods to a safe verb instead of forwarding raw strings"],"exampleFix":"// before\nconst method = rawLine; // 'GET /index HTTP/1.1'\nconst req = http.request({ host, method });\n\n// after\nconst method = rawLine.split(' ')[0].trim();\nconst req = http.request({ host, method });","handlingStrategy":"validation","validationCode":"const HTTP_TOKEN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\nif (method && !HTTP_TOKEN.test(method)) {\n  throw new Error(`invalid HTTP method: ${JSON.stringify(method)}`);\n}\nhttp.request({ host, method });","typeGuard":"const isHttpToken = (s) => typeof s === 'string' && s.length > 0 && /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(s);","tryCatchPattern":"try { http.request({ method }); } catch (e) { if (e.code === 'ERR_INVALID_HTTP_TOKEN') { /* sanitize: method = method.trim().split(' ')[0] */ } else throw e; }","preventionTips":["When parsing raw request lines, take only the first token as method","Trim whitespace from config-sourced methods","Whitelist allowed verbs instead of passing raw strings through"],"tags":["http","method","token","validation","node-compat"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}