denoland/deno · error · NodeError

ERR_HTTP2_CONNECT_SCHEME

ERR_HTTP2_CONNECT_SCHEME

Error message

The :scheme header is forbidden for CONNECT requests

What it means

HTTP/2 CONNECT requests must not carry the ':scheme' pseudo-header (RFC 7540 section 8.3). When preparing a headers array for a CONNECT request, presence of :scheme throws ERR_HTTP2_CONNECT_SCHEME (util.ts:693). The check is strict: even a matching scheme ('http'/'https') is rejected.

Source

Thrown at ext/node/polyfills/internal/http2/util.ts:693

      ArrayPrototypePush(
        additionalPsuedoHeaders,
        HTTP2_HEADER_AUTHORITY,
        authority,
      );
    }
    if (scheme === undefined) {
      scheme = StringPrototypeSlice(session[kProtocol], 0, -1);
      ArrayPrototypePush(additionalPsuedoHeaders, HTTP2_HEADER_SCHEME, scheme);
    }
    if (path === undefined) {
      ArrayPrototypePush(additionalPsuedoHeaders, HTTP2_HEADER_PATH, "/");
    }
  } else {
    if (authority === undefined) {
      throw new ERR_HTTP2_CONNECT_AUTHORITY();
    }
    if (scheme !== undefined) {
      throw new ERR_HTTP2_CONNECT_SCHEME();
    }
    if (path !== undefined) {
      throw new ERR_HTTP2_CONNECT_PATH();
    }
  }

  const rawHeaders = additionalPsuedoHeaders.length
    ? ArrayPrototypeConcat(additionalPsuedoHeaders, headers)
    : headers;

  if (headers[kSensitiveHeaders] !== undefined) {
    rawHeaders[kSensitiveHeaders] = headers[kSensitiveHeaders];
  }

  const headersList = buildNgHeaderString(
    rawHeaders,
    assertValidPseudoHeader,
    session[kStrictSingleValueFields],

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Delete ':scheme' from the headers array when the method is CONNECT.
  2. Split your request builder: one path for normal requests (defaults :scheme/:path) and one minimal path for CONNECT (only :method + :authority).
  3. In generic forwarders, filter the pseudo-header set by method before calling request().

Example fix

// before
const h = [...commonDefaults, ':scheme', 'https', ':method', 'CONNECT', ':authority', 'h:443'];

// after
const h = [':method', 'CONNECT', ':authority', 'h:443'];
Defensive patterns

Strategy: validation

Validate before calling

if (method === 'CONNECT') { headers = headers.filter((k, i) => i % 2 === 1 || k !== ':scheme'); }

Prevention

When it happens

Trigger: http2session.request() with ':method','CONNECT' plus ':scheme','https' in the headers array — usually a CONNECT request cloned from a normal request template that fills in :scheme automatically.

Common situations: Shared helper functions that always inject :scheme/:path defaults for normal requests being reused for CONNECT; proxy code ported from HTTP/1 where scheme was harmless; template objects spread into per-request headers.

Understand the failure class

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/6a8fddb6c502dfbe. Report an issue: GitHub.