denoland/deno · error · TypeError

Method is forbidden

Error message

Method is forbidden

What it means

After normalization to uppercase, the methods CONNECT, TRACE, and TRACK hit the forbidden branch of validateAndNormalizeMethod and throw TypeError 'Method is forbidden', as required by the Fetch spec — these verbs cannot be issued from web-platform fetch. TRACK is rejected alongside TRACE for historical IE-era reasons.

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 89f33cbef2)

Solutions

  1. Use a different HTTP method; if you need TRACE/CONNECT semantics, use a lower-level TCP/TLS client instead of fetch
  2. When forwarding inbound methods, filter out CONNECT/TRACE/TRACK (reply 405) before constructing the outgoing Request
  3. Map the operation onto a safe custom token method like 'X-Trace' if server and client are both yours

Example fix

// before
const method = inbound.method; // could be 'TRACE'
await fetch(target, { method });

// after
const FORBIDDEN = new Set(['CONNECT', 'TRACE', 'TRACK']);
const method = inbound.method.toUpperCase();
if (FORBIDDEN.has(method)) return new Response(null, { status: 405 });
await fetch(target, { method });
Defensive patterns

Strategy: type-guard

Validate before calling

const FORBIDDEN = new Set(['CONNECT', 'TRACE', 'TRACK']);
function safeMethod(m) {
  const upper = String(m).toUpperCase();
  if (FORBIDDEN.has(upper)) throw new Error(`forbidden method: ${upper}`);
  return upper;
}

Type guard

/** @param {string} m */
function isAllowedFetchMethod(m) {
  const u = m.toUpperCase();
  return /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(m) && !['CONNECT', 'TRACE', 'TRACK'].includes(u);
}

Prevention

When it happens

Trigger: fetch(url, { method: 'TRACE' }), new Request(url, { method: 'CONNECT' }), or any casing thereof ('trace', 'Connect'); also proxying a raw method string taken from an inbound request that happened to be TRACE/TRACK.

Common situations: Forwarding arbitrary incoming methods in a proxy/gateway, health-check scripts that try TRACE, or feature flags that map to forbidden verbs.

Understand the failure class

Related errors


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