denoland/deno · error · TypeError

Method is forbidden

Error message

Method is forbidden

What it means

validateAndNormalizeMethod upper-cases the method and rejects CONNECT, TRACE, and TRACK with TypeError "Method is forbidden". These methods are excluded from the fetch API for security/spec reasons (request smuggling, cross-site tracing); Deno throws at Request construction time. Custom token methods (e.g. PROPFIND) are allowed — only these three are forbidden.

Solutions

  1. Remove CONNECT/TRACE/TRACK from the set of methods your code can issue
  2. Use a raw TCP socket (Deno.connect) for CONNECT-style tunneling instead of fetch
  3. Filter user-configurable methods against a deny-list before constructing the Request

Example fix

// before
const FORBIDDEN = new Set(["connect", "trace", "track"]);
new Request("https://example.com", { method: "TRACE" }); // throws

// after
if (!FORBIDDEN.has(method.toLowerCase())) {
  new Request("https://example.com", { method });
}
Defensive patterns

Strategy: validation

Validate before calling

const FORBIDDEN_METHODS = new Set(["connect", "trace", "track"]);
if (FORBIDDEN_METHODS.has(String(method).toLowerCase())) {
  throw new Error(`Method ${method} is forbidden in fetch`);
}
const req = new Request(url, { method });

Type guard

const FORBIDDEN = new Set(["connect", "trace", "track"]);
function isAllowedFetchMethod(m: string): boolean {
  return !FORBIDDEN.has(m.toLowerCase());
}

Try / catch

try {
  new Request(url, { method });
} catch (err) {
  if (err instanceof TypeError && err.message === "Method is forbidden") {
    // reject the client request or substitute GET
  } else throw err;
}

Prevention

When it happens

Trigger: new Request(url, { method: "TRACE" }); { method: "CONNECT" }; { method: "track" } (case-insensitive).

Common situations: Generic HTTP clients being ported to fetch; test harnesses enumerating all standard methods; security scanners probing with TRACE; code driven by user-supplied method allow-lists that include forbidden methods.

Understand the failure class

Related errors


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

Appendix: source

Thrown at ext/fetch/23_request.js:287

 * @returns {string}
 */
function validateAndNormalizeMethod(m) {
  if (RegExpPrototypeExec(HTTP_TOKEN_CODE_POINT_RE, m) === null) {
    throw new TypeError("Method is not valid");
  }
  const upperCase = StringPrototypeToUpperCase(m);
  switch (upperCase) {
    case "DELETE":
    case "GET":
    case "HEAD":
    case "OPTIONS":
    case "POST":
    case "PUT":
      return upperCase;
    case "CONNECT":
    case "TRACE":
    case "TRACK":
      throw new TypeError("Method is forbidden");
  }
  return m;
}

class Request {
  /** @type {InnerRequest} */
  [_request];
  /** @type {Headers} */
  [_headersCache];
  [_getHeaders];
  [_headersGuard];
  [_signalCache];
  [_url];
  [_method];

  /** @type {Headers} */
  get [_headers]() {
    if (this[_headersCache] === undefined) {

View on GitHub (pinned to 9ad36f7a2c)