{"record":{"id":"436ac5e98d462546","repo":"denoland/deno","slug":"err-invalid-url-436ac5","errorCode":"ERR_INVALID_URL","errorMessage":"Invalid URL: ${urlStr}","messagePattern":"Invalid URL: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/https.ts","lineNumber":684,"sourceCode":"\nlet globalAgent = new (Agent as any)({\n  keepAlive: true,\n  scheduling: \"lifo\",\n  timeout: 5000,\n});\n\n/** Makes a request to an https server. */\nfunction request(...args: any[]) {\n  let options: any = {};\n\n  if (typeof args[0] === \"string\") {\n    const urlStr = ArrayPrototypeShift(args);\n    // Match Node: surface invalid URL strings as ERR_INVALID_URL.\n    let parsed;\n    try {\n      parsed = new URL(urlStr);\n    } catch {\n      throw new ERR_INVALID_URL(urlStr);\n    }\n    options = urlToHttpOptions(parsed);\n  } else if (ObjectPrototypeIsPrototypeOf(URL.prototype, args[0])) {\n    options = urlToHttpOptions(ArrayPrototypeShift(args));\n  }\n\n  if (args[0] && typeof args[0] !== \"function\") {\n    ObjectAssign(options, ArrayPrototypeShift(args));\n  }\n\n  options._defaultAgent = globalAgent;\n  ArrayPrototypeUnshift(args, options);\n\n  return new ClientRequest(args[0], args[1], args[2]);\n}\n\n// `agent-base` (used by `@npmcli/agent`, `http-proxy-agent`, etc.) figures\n// out whether a polymorphic agent should behave as https by scanning the","sourceCodeStart":666,"sourceCodeEnd":702,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/https.ts#L666-L702","documentation":"https.request(url, ...) accepts a plain string and parses it with the WHATWG URL constructor; strings the parser rejects (no scheme, invalid characters, unbalanced brackets) are surfaced as ERR_INVALID_URL, matching Node behavior. The error is strictly about URL syntax — passing a URL object skips string parsing entirely and cannot produce it.","triggerScenarios":"https.request('example.com/data') (no scheme); URLs containing spaces or raw non-ASCII/control characters; 'https://[::1' (unclosed IPv6 bracket); values read from env vars with trailing whitespace or newline.","commonSituations":"Building URLs by concatenation that drops or mangles the scheme; passing user-supplied or config-file strings straight to https.request; typo'd schemes like 'htps://'.","solutions":["Normalize before the call: prefix the scheme when missing, e.g. url.startsWith('http') ? url : 'https://' + url, and trim() the value.","Validate with new URL(str) (or URL.canParse(str) where available) at config-load time and fail with your own message.","Pass a URL object (new URL(...)) instead of a string to bypass string parsing."],"exampleFix":"// before\nconst req = https.request(`${host}/v1/users`); // host lacked a scheme -> ERR_INVALID_URL\n\n// after\nconst target = new URL(`https://${host.replace(/\\/+$/, '')}/v1/users`);\nconst req = https.request(target);","handlingStrategy":"validation","validationCode":"function parseRequestUrl(urlStr) {\n  const trimmed = String(urlStr).trim();\n  const withScheme = /^https?:\\/\\//i.test(trimmed) ? trimmed : `https://${trimmed}`;\n  try {\n    return new URL(withScheme);\n  } catch {\n    throw new Error(`Invalid request URL: ${JSON.stringify(urlStr)}`);\n  }\n}\nhttps.request(parseRequestUrl(rawTarget));","typeGuard":"function isParsableUrl(s) {\n  try { new URL(s); return true; } catch { return false; }\n}","tryCatchPattern":null,"preventionTips":["Always construct request URLs from a URL object or a template starting with https://.","Trim() values read from env vars and config files before using them as URLs.","Validate URLs once at config-load time, not per request."],"tags":["https","url","client","node-compat","validation"],"backgroundTag":"invalid-url","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}