denoland/deno · error · NodeError

ERR_HTTP2_CONNECT_AUTHORITY

ERR_HTTP2_CONNECT_AUTHORITY

Error message

:authority header is required for CONNECT requests

What it means

For HTTP/2 CONNECT requests built from a headers ARRAY, the ':authority' pseudo-header is mandatory (RFC 7540 section 8.3: CONNECT must carry :authority and must omit :scheme/:path). If method is CONNECT and no authority was resolved from the array, prepareRequestHeadersArray throws ERR_HTTP2_CONNECT_AUTHORITY (util.ts:690).

Source

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

  if (!connect || protocol !== undefined) {
    if (authority === undefined && headers[HTTP2_HEADER_HOST] === undefined) {
      authority = session[kAuthority];
      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(

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Add ':authority' with host:port to the headers array, e.g. [':method','CONNECT',':authority','example.com:443'].
  2. If the authority arrives as a Host header, map it: [':authority', hostHeader].
  3. Make sure you do not over-correct by also adding ':scheme' or ':path' — those throw ERR_HTTP2_CONNECT_SCHEME/PATH.

Example fix

// before
client.request([':method', 'CONNECT', ':path', '/']); // throws

// after
client.request([':method', 'CONNECT', ':authority', 'example.com:443']);
Defensive patterns

Strategy: validation

Validate before calling

const isConnect = (h) => h[':method'] === 'CONNECT' || h.includes?.('CONNECT');
if (isConnect(headers) && !hasAuthority(headers)) {
  headers = [...headers, ':authority', targetHost]; // or headers[':authority'] = targetHost
}

Try / catch

try { session.request(h); } catch (e) { if (e.code === 'ERR_HTTP2_CONNECT_AUTHORITY') { /* inject ':authority' from your target and retry */ } throw e; }

Prevention

When it happens

Trigger: Calling http2session.request([':method','CONNECT', ...]) or client.request(...) with method CONNECT and headers lacking ':authority' (and no host/authority fallback), e.g. [':method','CONNECT',':path','/tunnel'].

Common situations: Writing HTTP/2 tunneling/CONNECT-proxy code by copying a normal GET request template; forwarding a browser CONNECT request where the authority lived in a Host header that was dropped; version upgrades from HTTP/1 proxy code where Host: was implicit.

Related errors


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