{"record":{"id":"6dc2e678962b8c66","repo":"denoland/deno","slug":"unsupported-alpnprotocols-option-provided-h2","errorCode":null,"errorMessage":"Unsupported 'alpnProtocols' option provided. 'h2' and 'http/1.1' are automatically supported.","messagePattern":"Unsupported 'alpnProtocols' option provided\\. 'h2' and 'http/1\\.1' are automatically supported\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/http/00_serve.ts","lineNumber":1397,"sourceCode":"      automaticCompression,\n    );\n  }\n\n  const listenOpts = {\n    hostname: options.hostname ?? \"0.0.0.0\",\n    port: options.port ?? 8000,\n    reusePort: options.reusePort ?? false,\n    loadBalanced: options[kLoadBalanced] ?? false,\n    tcpBacklog: options.tcpBacklog,\n  };\n\n  if (options.certFile || options.keyFile) {\n    throw new TypeError(\n      \"Unsupported 'certFile' / 'keyFile' options provided: use 'cert' / 'key' instead.\",\n    );\n  }\n  if (options.alpnProtocols) {\n    throw new TypeError(\n      \"Unsupported 'alpnProtocols' option provided. 'h2' and 'http/1.1' are automatically supported.\",\n    );\n  }\n\n  let listener;\n  if (wantsHttps) {\n    if (!options.cert || !options.key) {\n      throw new TypeError(\n        \"Both 'cert' and 'key' must be provided to enable HTTPS\",\n      );\n    }\n    listenOpts.cert = options.cert;\n    listenOpts.key = options.key;\n    listenOpts.alpnProtocols = [\"h2\", \"http/1.1\"];\n    listener = listenTls(listenOpts);\n    listenOpts.port = listener.addr.port;\n  } else {\n    listener = listen(listenOpts);","sourceCodeStart":1379,"sourceCodeEnd":1415,"githubUrl":"https://github.com/denoland/deno/blob/abd22074e47c6a5cd14e9e4e84743f084aa5a575/ext/http/00_serve.ts#L1379-L1415","documentation":"Deno.serve does not let callers configure ALPN: when TLS is enabled it always negotiates 'h2' and 'http/1.1' automatically (listenOpts.alpnProtocols is hardcoded to both). Passing an `alpnProtocols` option throws this TypeError at startup to make the limitation explicit rather than accepting and ignoring a custom list.","triggerScenarios":"Adding `alpnProtocols: ['h2']` (or any value) to serve options, porting config from Deno.listenTls where alpnProtocols was configurable, or trying to restrict the server to a single protocol via options.","commonSituations":"Copy-paste from listenTls-based code, teams trying to disable HTTP/2 or force HTTP/3-adjacent settings, hardening checklists that list ALPN configuration.","solutions":["Delete the `alpnProtocols` option — h2 and http/1.1 are already enabled over TLS","If you need custom ALPN, drop to Deno.listenTls plus a manual HTTP loop instead of Deno.serve","For protocol-specific behavior, branch on `request.proto` (h2 vs http/1.1) inside the handler"],"exampleFix":"// before\nDeno.serve({ port: 443, cert, key, alpnProtocols: ['h2'], handler });\n\n// after\nDeno.serve({ port: 443, cert, key, handler }); // h2 + http/1.1 automatic","handlingStrategy":"validation","validationCode":"// Reject unsupported keys up front:\nif ('alpnProtocols' in opts) {\n  throw new Error('alpnProtocols is not configurable on Deno.serve; h2 and http/1.1 are automatic');\n}\nDeno.serve(opts);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not copy alpnProtocols from Deno.listenTls configs into serve options","Branch on request.proto inside the handler for protocol-specific behavior","Drop to listenTls only if you truly need custom ALPN negotiation"],"tags":["http","deno-serve","tls","alpn","http2","config"],"backgroundTag":"unsupported-config-option","analyzedSha":"abd22074e47c6a5cd14e9e4e84743f084aa5a575","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}