{"record":{"id":"f635d40c630b3352","repo":"denoland/deno","slug":"method-is-not-valid","errorCode":null,"errorMessage":"Method is not valid","messagePattern":"Method is not valid","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/23_request.js","lineNumber":273,"sourceCode":"  \"get\": \"GET\",\n  \"HEAD\": \"HEAD\",\n  \"head\": \"HEAD\",\n  \"OPTIONS\": \"OPTIONS\",\n  \"options\": \"OPTIONS\",\n  \"PATCH\": \"PATCH\",\n  \"POST\": \"POST\",\n  \"post\": \"POST\",\n  \"PUT\": \"PUT\",\n  \"put\": \"PUT\",\n};\n\n/**\n * @param {string} m\n * @returns {string}\n */\nfunction validateAndNormalizeMethod(m) {\n  if (RegExpPrototypeExec(HTTP_TOKEN_CODE_POINT_RE, m) === null) {\n    throw new TypeError(\"Method is not valid\");\n  }\n  const upperCase = StringPrototypeToUpperCase(m);\n  switch (upperCase) {\n    case \"DELETE\":\n    case \"GET\":\n    case \"HEAD\":\n    case \"OPTIONS\":\n    case \"POST\":\n    case \"PUT\":\n      return upperCase;\n    case \"CONNECT\":\n    case \"TRACE\":\n    case \"TRACK\":\n      throw new TypeError(\"Method is forbidden\");\n  }\n  return m;\n}\n","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/fetch/23_request.js#L255-L291","documentation":"validateAndNormalizeMethod runs the method against the HTTP token regex (HTTP_TOKEN_CODE_POINT_RE, per RFC 7230 tchar). If any character is not a valid token code point — spaces, non-ASCII, control chars, delimiters like '(', ')' — it throws TypeError 'Method is not valid'. This runs for every Request constructor and fetch() method option.","triggerScenarios":"new Request(url, { method: 'POST ' }) (trailing space), fetch(url, { method: 'größe' }) (non-ASCII), method containing CR/LF or characters like '\"' or '{}'.","commonSituations":"Methods built from unvalidated user input (custom X-HTTP-Method-Override headers), trailing whitespace from config files/env vars, or concatenated strings that accidentally include a newline.","solutions":["Trim and validate the method against ^[!#$%&'*+.^_`|~0-9A-Za-z-]+$ before using it","If the value comes from user input, reject non-token methods with a 400 rather than letting the TypeError escape","Hardcode known-good literals ('GET', 'POST', ...) at call sites"],"exampleFix":"// before\nconst method = userMethod; // e.g. 'POST '\\nawait fetch(url, { method });\n\n// after\nconst TOKEN_RE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\nconst method = userMethod.trim();\nif (!TOKEN_RE.test(method)) throw new Error(`invalid method: ${JSON.stringify(method)}`);\nawait fetch(url, { method });","handlingStrategy":"type-guard","validationCode":"const HTTP_METHOD_RE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\nfunction normalizeMethod(m) {\n  const s = String(m).trim();\n  if (!HTTP_METHOD_RE.test(s)) {\n    throw new Error(`invalid HTTP method: ${JSON.stringify(s)}`);\n  }\n  return s.toUpperCase();\n}","typeGuard":"/** @param {unknown} m */\nfunction isValidHttpMethod(m) {\n  return typeof m === 'string' && /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(m);\n}","tryCatchPattern":null,"preventionTips":["Trim and regex-validate methods sourced from users, env, or config","Use string literals for methods at call sites","Reject invalid inbound methods early with 400 in proxies"],"tags":["fetch","request","http-method","validation"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}