JuliusBrussee/caveman · error · TypeError
unsupported proxy protocol: ${proxy.protocol}
Error message
unsupported proxy protocol: ${proxy.protocol} What it means
proxyRequest selects the Node http/https request factory based on the proxy URL's protocol. Only http: and https: proxies are supported; anything else (socks5:, ftp:, etc.) causes an immediate TypeError before any connection is attempted.
Source
Thrown at packages/cli/src/proxy-fetch.ts:120
: ["http_proxy", "HTTP_PROXY", "all_proxy", "ALL_PROXY"];
const configured = readEnv(env, names);
return configured ? parseProxyUrl(configured) : null;
}
function proxyAuthHeader(proxy: URL): OutgoingHttpHeaders {
if (!proxy.username && !proxy.password) return {};
const credentials = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`;
return { "proxy-authorization": `Basic ${Buffer.from(credentials).toString("base64")}` };
}
function abortError(): Error {
return new DOMException("This operation was aborted", "AbortError") as unknown as Error;
}
function proxyRequest(proxy: URL): typeof httpsRequest {
if (proxy.protocol === "http:") return httpRequest;
if (proxy.protocol === "https:") return httpsRequest;
throw new TypeError(`unsupported proxy protocol: ${proxy.protocol}`);
}
/**
* Opens a CONNECT tunnel so TLS is negotiated with the target, not the proxy.
*
* Terminating TLS at the proxy would hand it the request and, for a signed
* release download, the bytes we are about to trust.
*/
function openTunnel(target: URL, proxy: URL, signal: AbortSignal | null): Promise<Socket> {
return new Promise((resolve, reject) => {
if (signal?.aborted) {
reject(abortError());
return;
}
let settled = false;
const finish = (error?: Error, socket?: Socket) => {
if (settled) {View on GitHub (pinned to 5184b3d11a)
Solutions
- Change the proxy to an HTTP(S) proxy: HTTP_PROXY=http://proxyhost:port (or https:// for a TLS proxy).
- If you need SOCKS, run an HTTP proxy in front (e.g. `privoxy`, or `gost -L http://:8080 -F socks5://...`) and point the env var at it.
- Check the protocol the URL actually parses to: `new URL(process.env.HTTPS_PROXY ?? '').protocol` and correct it.
- Remove quotes/scheme typos from the proxy env var value.
Example fix
// before HTTPS_PROXY=socks5://127.0.0.1:1080 // after HTTPS_PROXY=http://127.0.0.1:8118 # local HTTP proxy (e.g. privoxy) fronting the SOCKS tunnel
Defensive patterns
Strategy: validation
Validate before calling
const proxy = process.env.HTTPS_PROXY ? new URL(process.env.HTTPS_PROXY) : null;
if (proxy && proxy.protocol !== "http:" && proxy.protocol !== "https:")
throw new Error(`Proxy must be http(s), got: ${proxy.protocol}`); Type guard
function isHttpProxy(proxy: URL): boolean { return proxy.protocol === "http:" || proxy.protocol === "https:"; } Try / catch
try {
await fetch(url);
} catch (e) {
if (e instanceof TypeError && e.message.includes("unsupported proxy protocol")) {
console.error(`Fix proxy env var: ${e.message} (only http:/https: supported)`);
} else throw e;
} Prevention
- Only set HTTP(S)_PROXY to http:// or https:// URLs; never socks5://.
- Validate proxy env vars at startup with new URL() and check .protocol.
- Front SOCKS tunnels with an HTTP proxy (privoxy/gost) if SOCKS is required.
- Document the proxy requirement for your team's dev environments.
When it happens
Trigger: Configuring a proxy URL whose protocol is not http: or https: — e.g. HTTPS_PROXY=socks5://host:1080 or a malformed proxy env var parsed into a URL with an unexpected scheme.
Common situations: Developers pointing HTTPS_PROXY/HTTP_PROXY at a SOCKS proxy (ssh -D tunnels, corporate SOCKS gateways); typos like 'socks5h://'; proxy URLs missing scheme so URL parsing yields odd protocols.
Related errors
- binary download failed: ${error.message}
- AbortError
- cave_mastra_max_steps_invalid
- cave_budget_denomination_ambiguous
- cave_budget_max_invalid
AI-assisted analysis of JuliusBrussee/caveman@5184b3d11a (2026-08-31).
Data as JSON: /api/errors/f22154613afa2c9d.
Report an issue: GitHub.