{"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/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fetch/23_request.js#L255-L291","documentation":"Request's constructor normalizes the method via validateAndNormalizeMethod, which first tests the string against the HTTP token code-point regex (visible ASCII token characters only: A-Z a-z 0-9 and !#$%&'*+-.^_`|~). A method containing spaces, slashes, parentheses, non-ASCII characters, or an empty string fails the regex and throws TypeError \"Method is not valid\".","triggerScenarios":"new Request(url, { method: \"\" }); method: \"GET /path\"; method: \"POST(json)\"; method with a trailing newline or any non-token character; methods read from unsanitized config or headers.","commonSituations":"Building the method from user input or a template string; empty-string defaults from optional config (config.method ?? \"\" ); method strings transported through systems that append whitespace or CRLF.","solutions":["Use a plain token method string: GET, POST, or a custom token like PROPFIND","Trim whitespace and reject empty strings before constructing the Request","Validate the method against /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ in your config loader"],"exampleFix":"// before\nconst method = config.method ?? \"\";\nnew Request(\"https://example.com\", { method }); // throws when empty or \"GET /x\"\n\n// after\nconst TOKEN_RE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\nconst method = config.method && TOKEN_RE.test(config.method) ? config.method : \"GET\";\nnew Request(\"https://example.com\", { method });","handlingStrategy":"validation","validationCode":"const HTTP_TOKEN_RE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\nif (!HTTP_TOKEN_RE.test(method) || method === \"\") {\n  throw new Error(`Invalid HTTP method: ${JSON.stringify(method)}`);\n}\nconst req = new Request(url, { method });","typeGuard":"const HTTP_TOKEN_RE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\nfunction isValidHttpMethod(m: unknown): m is string {\n  return typeof m === \"string\" && HTTP_TOKEN_RE.test(m);\n}","tryCatchPattern":"try {\n  new Request(url, { method });\n} catch (err) {\n  if (err instanceof TypeError && err.message === \"Method is not valid\") {\n    // sanitize: fall back to a safe default method\n    new Request(url, { method: \"GET\" });\n  } else throw err;\n}","preventionTips":["Validate method strings at the config/API boundary, not at Request construction","Trim and reject empty strings before use","Whitelist known methods and treat anything else as custom-but-token-only"],"tags":["fetch","request","http-method","validation"],"backgroundTag":"invalid-http-method","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}