denoland/deno · error · NodeTypeError
ERR_INVALID_URL
ERR_INVALID_URL
Error message
Invalid URL: ${urlStr} What it means
When ClientRequest receives a string as its first argument, the polyfill parses it with new URL(urlStr). Deno's Web URL throws a generic TypeError on bad input, so the polyfill wraps it to attach Node's ERR_INVALID_URL code and the 'Invalid URL: <input>' message. It fires only for the string-input form; URL objects and options objects go through other branches.
Source
Thrown at ext/node/polyfills/_http_client.js:464
function isURL(input) {
return ObjectPrototypeIsPrototypeOf(URL.prototype, input);
}
function ClientRequest(input, options, cb) {
FunctionPrototypeCall(OutgoingMessage, this);
if (typeof input === "string") {
const urlStr = input;
// Match Node: `new URL(...)` in ClientRequest surfaces as
// ERR_INVALID_URL (node's internal URL constructor calls
// bindingUrl.parse with raiseException=true). Deno's Web URL
// throws a generic TypeError, so wrap it to attach the code.
let parsed;
try {
parsed = new URL(urlStr);
} catch {
throw new ERR_INVALID_URL(urlStr);
}
input = urlToHttpOptions(parsed);
} else if (isURL(input)) {
input = urlToHttpOptions(input);
} else {
cb = options;
options = input;
input = null;
}
if (typeof options === "function") {
cb = options;
options = input || kEmptyObject;
} else {
options = ObjectAssign(input || {}, options);
}
let agent = options.agent;View on GitHub (pinned to 89f33cbef2)
Solutions
- Include the scheme: 'http://' + host + path, or better, construct with new URL(path, base) first
- Validate before calling: if (!URL.canParse(urlStr)) fail with your own message
- Log the offending string when catching to find where the malformed value originates
Example fix
// before
const req = http.request(`${cfg.host}/api`); // cfg.host = 'api.example.com'
// after
const target = new URL('/api', `http://${cfg.host}`);
const req = http.request(target); Defensive patterns
Strategy: validation
Validate before calling
// Node >= 18.17 / Deno
if (!URL.canParse(urlStr)) {
throw new Error(`invalid target URL: ${JSON.stringify(urlStr)}`);
}
http.request(urlStr); Type guard
function isParseableUrl(v) {
if (typeof v !== 'string' || !v) return false;
try { new URL(v); return true; } catch { return false; }
} Try / catch
try { http.get(urlStr, cb); } catch (e) { if (e.code === 'ERR_INVALID_URL') { /* log e.input, reject user input */ } else throw e; } Prevention
- Always construct targets via new URL(path, base)
- Reject URLs missing a scheme at config-load time
- Never interpolate undefined/null into URL template strings
When it happens
Trigger: http.get('not-a-url'); http.request('example.com/path') (missing protocol); malformed bracket syntax like 'http://[::1:80/x'; strings built by concatenation that drop the scheme or contain spaces.
Common situations: Forgetting the http:// prefix when the value comes from an env var or config that stores a bare host; user-supplied URLs pasted into a CLI; template literals that interpolate undefined into the URL string.
Related errors
- ERR_INVALID_ARG_TYPE
- ERR_UNESCAPED_CHARACTERS
- ERR_INVALID_HTTP_TOKEN
- ERR_HTTP_HEADERS_SENT
- ERR_INVALID_HTTP_TOKEN
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/9cca0b286898ab5d.
Report an issue: GitHub.