{"record":{"id":"6a8fddb6c502dfbe","repo":"denoland/deno","slug":"err-http2-connect-scheme","errorCode":"ERR_HTTP2_CONNECT_SCHEME","errorMessage":"The :scheme header is forbidden for CONNECT requests","messagePattern":"The :scheme header is forbidden for CONNECT requests","errorType":"validation","errorClass":"NodeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/http2/util.ts","lineNumber":693,"sourceCode":"      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(\n    rawHeaders,\n    assertValidPseudoHeader,\n    session[kStrictSingleValueFields],","sourceCodeStart":675,"sourceCodeEnd":711,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/http2/util.ts#L675-L711","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Delete ':scheme' from the headers array when the method is CONNECT.","Split your request builder: one path for normal requests (defaults :scheme/:path) and one minimal path for CONNECT (only :method + :authority).","In generic forwarders, filter the pseudo-header set by method before calling request()."],"exampleFix":"// before\nconst h = [...commonDefaults, ':scheme', 'https', ':method', 'CONNECT', ':authority', 'h:443'];\n\n// after\nconst h = [':method', 'CONNECT', ':authority', 'h:443'];","handlingStrategy":"validation","validationCode":"if (method === 'CONNECT') { headers = headers.filter((k, i) => i % 2 === 1 || k !== ':scheme'); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Split request builders: normal requests vs CONNECT","Assert CONNECT header arrays contain only :method and :authority"],"tags":["http2","connect","proxy","pseudo-header","node-compat"],"backgroundTag":"http2-connect-headers","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"}