denoland/deno · critical · TypeError
Invalid URL
Error message
Invalid URL: ${raw} What it means
In the node:http proxy support, parseProxyUrl validates values read from proxy environment variables (http_proxy/HTTP_PROXY, https_proxy/HTTPS_PROXY). In 'env' mode - active when NODE_USE_ENV_PROXY=1 or --use-env-proxy - a present-but-non-string value throws TypeError('Invalid URL: <value>'), mirroring whatwg URL constructor semantics that Node v24 surfaces at request time. The error propagates through resolveAgentProxyConfig and lands on the first request that needs the proxy.
Solutions
- Ensure proxy env vars are strings: set them as String(value) or via a proper shell export.
- Unset the malformed variable (or set it to empty string, which is treated as 'no proxy') so requests go direct.
- If you inject env programmatically, validate http_proxy/https_proxy/no_proxy with typeof === 'string' before startup.
Example fix
// before
Deno.env.set('HTTP_PROXY', 123 as any); // non-string
// NODE_USE_ENV_PROXY=1 -> first request throws TypeError
// after
Deno.env.set('HTTP_PROXY', 'http://proxy.local:8080'); Defensive patterns
Strategy: validation
Validate before calling
function assertProxyEnvStrings(env) {
for (const k of ['http_proxy', 'HTTP_PROXY', 'https_proxy', 'HTTPS_PROXY']) {
const v = env[k];
if (v === undefined || v === '') continue;
if (typeof v !== 'string') throw new Error(`${k} must be a string, got ${typeof v}`);
new URL(v); // parseability pre-check
}
}
assertProxyEnvStrings(Deno.env.toObject()); Try / catch
try {
http.get('http://example.com/', cb);
} catch (err) {
if (err instanceof TypeError && String(err.message).startsWith('Invalid URL')) {
// proxy env var is malformed: fix/unset HTTP(S)_PROXY, then retry
} else throw err;
} Prevention
- Set proxy variables only as full URL strings via shell exports.
- Validate injected env values (typeof string + URL parse) at startup before NODE_USE_ENV_PROXY matters.
- An empty-string value means 'no proxy' - prefer that over deleting when going direct.
When it happens
Trigger: NODE_USE_ENV_PROXY=1 with an env-like source (or buildProxyConfig(env, 'env')) where http_proxy is a non-string non-empty value, e.g. a number or boolean injected programmatically; then any http request triggers maybeInitFromEnv and throws.
Common situations: Programmatically seeded process.env/privileged env with non-string values; test harnesses passing objects where strings belong; tooling that copies env JSON verbatim into the runtime; virtually impossible via a real shell, which only produces string env values.
Related errors
- ERR_PROXY_INVALID_CONFIG
- ERR_INVALID_URL
- Both 'cert' and 'key' must be provided to enable HTTPS
- ERR_HTTP_BODY_NOT_ALLOWED
- ERR_HTTP_CONTENT_LENGTH_MISMATCH
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/4ef9362f5abc5d91.
Report an issue: GitHub.
Appendix: source
Thrown at ext/node/polyfills/_http_proxy.js:108
}
function readEnvKey(env, keys) {
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
if (env[k] !== undefined && env[k] !== "") {
return env[k];
}
}
return undefined;
}
const CRLF_RE = new SafeRegExp(/[\r\n]/);
function parseProxyUrl(raw, kind, mode) {
if (raw === undefined || raw === null || raw === "") return null;
if (typeof raw !== "string") {
if (mode === "env") {
throw new TypeError(`Invalid URL: ${raw}`);
}
throw new ERR_PROXY_INVALID_CONFIG(
`Invalid proxy URL for ${kind}: must be a string`,
);
}
// CRLF injection guard - check raw string before URL parsing strips them.
// Matches Node's CRLF rejection in the proxy URL validator. We surface this
// even for env-derived URLs so the auth tests get the expected error class.
if (RegExpPrototypeExec(CRLF_RE, raw) !== null) {
throw new ERR_PROXY_INVALID_CONFIG(`Invalid proxy URL: ${raw}`);
}
let url;
try {
url = new URL(raw);
} catch {
if (mode === "env") {
throw new TypeError(`Invalid URL: ${raw}`);
}View on GitHub (pinned to 9ad36f7a2c)