oven-sh/bun · error · TypeError

UnsupportedProxyProtocol

UnsupportedProxyProtocol

Error message

UnsupportedProxyProtocol

What it means

Thrown by Bun's HTTP client when a proxy URL is configured but its scheme is neither empty nor http/https. Bun only supports HTTP-style (forward and CONNECT) proxies: the check in src/http/HTTPThread.rs (`url.protocol.is_empty() || url.has_http_like_protocol()`) rejects anything else before any socket is opened. It surfaces as a rejected fetch promise (or Bun.connect error) with `code: "UnsupportedProxyProtocol"` (see test/js/bun/http/proxy.test.ts:378).

Source

Thrown at src/http/error.rs:98

    #[error("WantWrite")]
    WantWrite,
    #[error("HTTP3HandshakeFailed")]
    HTTP3HandshakeFailed,
    #[error("HTTP3ProtocolError")]
    HTTP3ProtocolError,
    #[error("HTTP3HeaderEncodingError")]
    HTTP3HeaderEncodingError,
    #[error("DNSResolutionFailed")]
    DNSResolutionFailed,
    #[error("HTTP3StreamReset")]
    HTTP3StreamReset,
    #[error("HTTP3ContentLengthMismatch")]
    HTTP3ContentLengthMismatch,
    #[error("FailedToOpenSocket")]
    FailedToOpenSocket,
    #[error("InvalidCRL")]
    InvalidCRL,
    #[error("UnsupportedProxyProtocol")]
    UnsupportedProxyProtocol,
    #[error(transparent)]
    Cert(#[from] CertError),
    #[error(transparent)]
    Alloc(#[from] bun_alloc::AllocError),
    #[error(transparent)]
    Hpack(#[from] crate::lshpack::HpackError),
    #[error(transparent)]
    Core(#[from] bun_core::Error),
    #[error(transparent)]
    Sys(#[from] bun_errno::SystemErrno),
    #[error(transparent)]
    Zlib(bun_zlib::ZlibError),
    #[error(transparent)]
    Brotli(bun_brotli::Error),
    #[error(transparent)]
    Zstd(bun_zstd::ZstdError),
    #[error(transparent)]

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Change the proxy URL to an http:// or https:// scheme (e.g. a local HTTP-to-SOCKS bridge such as privoxy/gost if only SOCKS exists)
  2. If the string was scheme-less, keep it empty-protocol (Bun accepts an empty protocol) or explicitly write http://proxyhost:port
  3. Unset or fix the offending env var (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, BUN_CONFIG_PROXY) if you did not pass `proxy` explicitly
  4. For SOCKS-only environments, run a local HTTP proxy that forwards to SOCKS and point Bun at that
  5. Catch the rejection and fail with a clear message if an unsupported proxy is a supported configuration in your app

Example fix

// before
await fetch("https://httpbin.org/get", { proxy: "socks5://asdf.com" });
// TypeError: UnsupportedProxyProtocol

// after
await fetch("https://httpbin.org/get", { proxy: "http://127.0.0.1:8080" }); // HTTP proxy that bridges to SOCKS upstream
Defensive patterns

Strategy: validation

Validate before calling

function assertSupportedProxy(proxy: string | URL | undefined) {
  if (proxy == null) return;
  const proto = new URL(proxy).protocol.replace(":", "");
  if (proto !== "http" && proto !== "https") {
    throw new Error(
      `Bun only supports http/https proxies, got '${proto}://' — use an HTTP-to-SOCKS bridge`
    );
  }
}
assertSupportedProxy(process.env.HTTP_PROXY);
await fetch("https://example.com", { proxy: "http://127.0.0.1:8080" });

Type guard

function isUnsupportedProxyProtocolError(e: unknown): e is Error & { code: "UnsupportedProxyProtocol" } {
  return e instanceof Error && (e as any).code === "UnsupportedProxyProtocol";
}

Try / catch

try {
  await fetch(url, { proxy });
} catch (e) {
  if (isUnsupportedProxyProtocolError(e)) {
    // fall back to direct, or surface a config error — do not retry the same proxy
    throw new Error(`Proxy '${proxy}' uses an unsupported scheme; use http:// or https://`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling fetch(url, { proxy: "socks5://..." }) or any proxy string whose scheme is not http:// or https:// (ftp://, socks4://, socks5h://, etc.), or setting HTTP_PROXY / HTTPS_PROXY / BUN_CONFIG_PROXY to a non-HTTP scheme so every outbound fetch/Bun.connect inherits it. Also triggered via WebSocket through such a proxy (src/jsc/bindings/webcore/WebSocket.cpp mirrors the fetch behavior).

Common situations: Corporate SOCKS proxies (very common in enterprise/VPN setups), copy-pasting an scp/ssh-style proxy string, curl users assuming socks5h works like in curl, CI environments that export ALL_PROXY=socks5://... globally, or a proxy string missing the scheme where the URL parser assigned an unexpected protocol.

Related errors


AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16). Data as JSON: /api/errors/0bc9cb20d45e1515. Report an issue: GitHub.