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
- 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)
- If the string was scheme-less, keep it empty-protocol (Bun accepts an empty protocol) or explicitly write http://proxyhost:port
- Unset or fix the offending env var (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, BUN_CONFIG_PROXY) if you did not pass `proxy` explicitly
- For SOCKS-only environments, run a local HTTP proxy that forwards to SOCKS and point Bun at that
- 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
- Validate the proxy scheme at config-load time, before the first fetch
- Keep env-var-driven proxy config (HTTP_PROXY/HTTPS_PROXY/BUN_CONFIG_PROXY) out of CI secrets where socks5 schemes sneak in
- Document that Bun supports HTTP CONNECT proxies only; add a lint/test asserting your proxy constant starts with http
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.