denoland/deno · error · TypeError

The url passed into 'proxy.url' has an invalid scheme for th

Error message

The url passed into 'proxy.url' has an invalid scheme for this transport.

What it means

Deno.createHttpClient() validates the proxy URL scheme against proxy.transport (ext/fetch/22_http_client.js): transport "http" rejects urls starting with https:, socks5:, socks5h:; transport "https" rejects http:, socks5:, socks5h:; transport "socks5" REQUIRES a socks5:/socks5h: prefix; tcp/unix/vskip perform no check. If the transport key is omitted entirely, transport defaults to "http" with no scheme check in this JS layer.

Source

Thrown at ext/fetch/22_http_client.js:42

  // Don't mutate the caller's options object. Historically `caCerts` and
  // `proxy.transport` were written back onto whatever the user passed in,
  // which broke reuse of a single options object across multiple calls
  // (denoland/deno#29347).
  options = ObjectAssign({ __proto__: null }, options);
  options.caCerts = options.caCerts ?? [];
  if (options.proxy) {
    const proxy = ObjectAssign({ __proto__: null }, options.proxy);
    options.proxy = proxy;
    if (ObjectHasOwn(proxy, "transport")) {
      switch (proxy.transport) {
        case "http": {
          const url = proxy.url;
          if (
            StringPrototypeStartsWith(url, "https:") ||
            StringPrototypeStartsWith(url, "socks5:") ||
            StringPrototypeStartsWith(url, "socks5h:")
          ) {
            throw new TypeError(
              `The url passed into 'proxy.url' has an invalid scheme for this transport.`,
            );
          }
          proxy.transport = "http";
          break;
        }
        case "https": {
          const url = proxy.url;
          if (
            StringPrototypeStartsWith(url, "http:") ||
            StringPrototypeStartsWith(url, "socks5:") ||
            StringPrototypeStartsWith(url, "socks5h:")
          ) {
            throw new TypeError(
              `The url passed into 'proxy.url' has an invalid scheme for this transport.`,
            );
          }
          proxy.transport = "http";

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Match transport to scheme: https:// proxies need transport: "https"; socks5:// or socks5h:// urls need transport: "socks5"
  2. Plain http:// proxies work with transport: "http" (or omit the transport key - it defaults to http)
  3. Verify the URL string for typos, leading whitespace, or an uppercase scheme copied from environment variables

Example fix

// before
const client = Deno.createHttpClient({
  proxy: { transport: "http", url: "https://proxy.corp:3129" }, // throws
});

// after
const client = Deno.createHttpClient({
  proxy: { transport: "https", url: "https://proxy.corp:3129" },
});
Defensive patterns

Strategy: validation

Validate before calling

function checkProxy(transport: string, url: string) {
  const s = url.toLowerCase();
  if (transport === "http" && (s.startsWith("https:") || s.startsWith("socks5:"))) throw new Error("bad proxy scheme");
  if (transport === "https" && (s.startsWith("http:") || s.startsWith("socks5:"))) throw new Error("bad proxy scheme");
  if (transport === "socks5" && !(s.startsWith("socks5:") || s.startsWith("socks5h:"))) throw new Error("bad proxy scheme");
}
checkProxy("https", proxyUrl); // before createHttpClient

Type guard

function isValidProxyUrl(transport: string, url: string): boolean {
  const s = url.trim().toLowerCase();
  switch (transport) {
    case "http": return !s.startsWith("https:") && !s.startsWith("socks5:") && !s.startsWith("socks5h:");
    case "https": return !s.startsWith("http:") && !s.startsWith("socks5:") && !s.startsWith("socks5h:");
    case "socks5": return s.startsWith("socks5:") || s.startsWith("socks5h:");
    case "tcp": case "unix": case "vsock": return true;
    default: return false;
  }
}

Try / catch

try { return Deno.createHttpClient(opts); } catch (e) {
  if (e instanceof TypeError && e.message.includes("invalid scheme for this transport")) {
    throw new Error(`proxy url ${opts.proxy?.url} does not match transport ${opts.proxy?.transport}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Deno.createHttpClient({ proxy: { transport: "http", url: "https://proxy.corp:3129" } }); or transport "socks5" with an http:// url; also transport "https" with a plain http:// proxy url.

Common situations: Corporate environments where the proxy endpoint itself is https:// (requires transport "https"); migrating curl-style configs where scheme implied the transport; SOCKS setups where the developer forgot transport: "socks5".

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/e2f143cd9e6b80bc. Report an issue: GitHub.