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

  1. Change the proxy to an HTTP(S) proxy: HTTP_PROXY=http://proxyhost:port (or https:// for a TLS proxy).
  2. 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.
  3. Check the protocol the URL actually parses to: `new URL(process.env.HTTPS_PROXY ?? '').protocol` and correct it.
  4. 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

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


AI-assisted analysis of JuliusBrussee/caveman@5184b3d11a (2026-08-31). Data as JSON: /api/errors/f22154613afa2c9d. Report an issue: GitHub.