{"record":{"id":"20a99c7a656f997b","repo":"denoland/deno","slug":"err-http2-connect-authority","errorCode":"ERR_HTTP2_CONNECT_AUTHORITY","errorMessage":":authority header is required for CONNECT requests","messagePattern":":authority header is required for CONNECT requests","errorType":"validation","errorClass":"NodeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/http2/util.ts","lineNumber":690,"sourceCode":"  if (!connect || protocol !== undefined) {\n    if (authority === undefined && headers[HTTP2_HEADER_HOST] === undefined) {\n      authority = session[kAuthority];\n      ArrayPrototypePush(\n        additionalPsuedoHeaders,\n        HTTP2_HEADER_AUTHORITY,\n        authority,\n      );\n    }\n    if (scheme === undefined) {\n      scheme = StringPrototypeSlice(session[kProtocol], 0, -1);\n      ArrayPrototypePush(additionalPsuedoHeaders, HTTP2_HEADER_SCHEME, scheme);\n    }\n    if (path === undefined) {\n      ArrayPrototypePush(additionalPsuedoHeaders, HTTP2_HEADER_PATH, \"/\");\n    }\n  } else {\n    if (authority === undefined) {\n      throw new ERR_HTTP2_CONNECT_AUTHORITY();\n    }\n    if (scheme !== undefined) {\n      throw new ERR_HTTP2_CONNECT_SCHEME();\n    }\n    if (path !== undefined) {\n      throw new ERR_HTTP2_CONNECT_PATH();\n    }\n  }\n\n  const rawHeaders = additionalPsuedoHeaders.length\n    ? ArrayPrototypeConcat(additionalPsuedoHeaders, headers)\n    : headers;\n\n  if (headers[kSensitiveHeaders] !== undefined) {\n    rawHeaders[kSensitiveHeaders] = headers[kSensitiveHeaders];\n  }\n\n  const headersList = buildNgHeaderString(","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/http2/util.ts#L672-L708","documentation":"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).","triggerScenarios":"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'].","commonSituations":"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.","solutions":["Add ':authority' with host:port to the headers array, e.g. [':method','CONNECT',':authority','example.com:443'].","If the authority arrives as a Host header, map it: [':authority', hostHeader].","Make sure you do not over-correct by also adding ':scheme' or ':path' — those throw ERR_HTTP2_CONNECT_SCHEME/PATH."],"exampleFix":"// before\nclient.request([':method', 'CONNECT', ':path', '/']); // throws\n\n// after\nclient.request([':method', 'CONNECT', ':authority', 'example.com:443']);","handlingStrategy":"validation","validationCode":"const isConnect = (h) => h[':method'] === 'CONNECT' || h.includes?.('CONNECT');\nif (isConnect(headers) && !hasAuthority(headers)) {\n  headers = [...headers, ':authority', targetHost]; // or headers[':authority'] = targetHost\n}","typeGuard":null,"tryCatchPattern":"try { session.request(h); } catch (e) { if (e.code === 'ERR_HTTP2_CONNECT_AUTHORITY') { /* inject ':authority' from your target and retry */ } throw e; }","preventionTips":["For CONNECT always set :authority to host:port","Do not rely on a 'host' header to carry CONNECT authority"],"tags":["http2","connect","proxy","headers","node-compat"],"backgroundTag":"http2-connect-authority","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}