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
- Remove CONNECT/TRACE/TRACK from the set of methods your code can issue
- Use a raw TCP socket (Deno.connect) for CONNECT-style tunneling instead of fetch
- 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
- Filter CONNECT/TRACE/TRACK out of any user-supplied method allow-list
- Remember the check is case-insensitive ('track' throws too)
- Use raw sockets (Deno.connect) for tunneling, never fetch with CONNECT
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Method is not valid
- Request with GET/HEAD method cannot have body
- Blob URL fetch only supports GET method
- Body is unusable
- Cannot read headers: request closed
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)