{"record":{"id":"21bc39b74e77ff88","repo":"denoland/deno","slug":"err-invalid-url-21bc39","errorCode":"ERR_INVALID_URL","errorMessage":"Invalid URL: ${url}","messagePattern":"Invalid URL: (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/url.ts","lineNumber":898,"sourceCode":"      // assume that it's an IPv6 address.\n      const ipv6Hostname = isIpv6Hostname(hostname);\n\n      // validate a little.\n      if (!ipv6Hostname) {\n        rest = getHostname(this, rest, hostname);\n      }\n\n      if (this.hostname.length > hostnameMaxLen) {\n        this.hostname = \"\";\n      } else {\n        // Hostnames are always lower case.\n        this.hostname = StringPrototypeToLowerCase(this.hostname);\n      }\n\n      if (this.hostname !== \"\") {\n        if (ipv6Hostname) {\n          if (RegExpPrototypeTest(forbiddenHostCharsIpv6, this.hostname)) {\n            throw new ERR_INVALID_URL(url);\n          }\n        } else {\n          // IDNA Support: Returns a punycoded representation of \"domain\".\n          // It only converts parts of the domain name that\n          // have non-ASCII characters, i.e. it doesn't matter if\n          // you call it with a domain that already is ASCII-only.\n\n          // Use lenient mode (`true`) to try to support even non-compliant\n          // URLs.\n          this.hostname = idnaToASCII(this.hostname);\n\n          // Prevent two potential routes of hostname spoofing.\n          // 1. If this.hostname is empty, it must have become empty due to toASCII\n          //    since we checked this.hostname above.\n          // 2. If any of forbiddenHostChars appears in this.hostname, it must have\n          //    also gotten in due to toASCII. This is since getHostname would have\n          //    filtered them out otherwise.\n          // Rather than trying to correct this by moving the non-host part into","sourceCodeStart":880,"sourceCodeEnd":916,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/url.ts#L880-L916","documentation":"The legacy `url.parse()` hardens IPv6 hostnames: for bracketed IPv6 hosts, the hostname must contain only characters allowed in IPv6 literals; anything in the forbidden set (control characters, spaces, %, /, ?, # and similar) throws ERR_INVALID_URL with the whole input URL embedded in the message. This mirrors Node's hardening of the legacy parser against malformed or crafted hostnames.","triggerScenarios":"`url.parse('http://[fe80::1/foo]')` with a slash inside the brackets; a stray #, ?, or space inside the bracket literal; hand-concatenated URLs where a path character lands inside the host portion.","commonSituations":"Parsing untrusted URLs from logs, Referer headers, or scraped HTML; building URLs by string concatenation instead of the URL API.","solutions":["Pre-validate with the WHATWG parser: `new URL(input)` rejects malformed hosts with clearer errors","Fix the IPv6 literal to contain only hex digits, colons, dots, and optionally a zone id","Percent-encode IPv6 zone ids as %25<zone> or strip them before parsing"],"exampleFix":"// before\nconst u = url.parse(\"http://[fe80::1/foo]\"); // ERR_INVALID_URL\n\n// after\nconst u = new URL(\"http://[fe80::1]/foo\"); // strict WHATWG parsing\n// or fix the literal, then keep the legacy parser:\nconst u2 = url.parse(\"http://[fe80::1]/foo\");","handlingStrategy":"validation","validationCode":"try {\n  new URL(input); // WHATWG pre-filter for malformed hosts\n} catch {\n  throw new Error(`rejecting malformed URL: ${input}`);\n}\nconst u = url.parse(input);","typeGuard":null,"tryCatchPattern":"try {\n  const u = url.parse(input);\n} catch (e: any) {\n  if (e?.code === \"ERR_INVALID_URL\") {\n    throw new Error(`rejecting malformed URL: ${input}`);\n  }\n  throw e;\n}","preventionTips":["Pre-validate untrusted input with new URL() before legacy url.parse","Keep IPv6 literals to hex digits, colons and dots","Percent-encode IPv6 zone ids (%25eth0) or strip them"],"tags":["url","ipv6","parsing","node-compat"],"backgroundTag":"invalid-url","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}