{"record":{"id":"3b918da2ba8b93dc","repo":"denoland/deno","slug":"both-cert-and-key-must-be-provided-to-enable-h","errorCode":null,"errorMessage":"Both 'cert' and 'key' must be provided to enable HTTPS","messagePattern":"Both 'cert' and 'key' must be provided to enable HTTPS","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/http/00_serve.ts","lineNumber":1382,"sourceCode":"    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);\n    listenOpts.port = listener.addr.port;\n  }\n\n  const addr = listener.addr;\n\n  const onListen = (scheme) => {\n    if (options.onListen) {\n      options.onListen(addr);","sourceCodeStart":1364,"sourceCodeEnd":1400,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/http/00_serve.ts#L1364-L1400","documentation":"Thrown by Deno.serve() when TLS is requested by supplying only one half of the key pair. The server checks wantsHttps (true when any of cert/key/certFile/keyFile is set via hasTlsKeyPairOptions) and then requires both options.cert and options.key to be non-empty before calling listenTls. Providing only 'cert' or only 'key' (or an empty string for one of them) aborts listener creation.","triggerScenarios":"Calling Deno.serve({ port, cert: certPem }) without key, or Deno.serve({ key: keyPem }) without cert; passing an empty string '' for one of them; porting code from Deno.serve({ certFile, keyFile }) by renaming only one option to cert.","commonSituations":"Migrating from the removed certFile/keyFile options to inline cert/key PEM strings; reading only one of the two PEM files from disk/env; trailing whitespace or a failed fs.readFileSync returning undefined for one field; .env variable typos (CERT vs KEY names).","solutions":["Pass both options: Deno.serve({ port, cert: certPem, key: keyPem }) where both are the full PEM strings (-----BEGIN CERTIFICATE-----... / -----BEGIN PRIVATE KEY-----...).","Load both PEM files explicitly: const cert = await Deno.readText('cert.pem'); const key = await Deno.readText('key.pem');","If you did not intend HTTPS, remove the cert/key/certFile/keyFile option entirely.","If you meant to use file paths, note certFile/keyFile are unsupported (a separate error) - read the files yourself and pass their contents."],"exampleFix":"// before\nconst server = Deno.serve({ port: 8443, cert: await Deno.readText(\"cert.pem\") });\n\n// after\nconst server = Deno.serve({\n  port: 8443,\n  cert: await Deno.readText(\"cert.pem\"),\n  key: await Deno.readText(\"key.pem\"),\n});","handlingStrategy":"validation","validationCode":"const cert = await Deno.readText(\"cert.pem\");\nconst key = await Deno.readText(\"key.pem\");\nif (!cert || !key) {\n  throw new Error(\"TLS requires both a non-empty cert and key PEM\");\n}\nconst server = Deno.serve({ port: 8443, cert, key, handler });","typeGuard":"function hasCompleteTlsPair(o: { cert?: string; key?: string }): boolean {\n  return Boolean(o.cert) && Boolean(o.key);\n}","tryCatchPattern":"try { Deno.serve({ ...opts, cert, key }); } catch (e) { if (e instanceof TypeError && e.message.includes(\"cert\")) { log.fatal(\"TLS misconfigured: supply both cert and key PEMs\"); } throw e; }","preventionTips":["Keep cert/key loading in one helper that reads both files or neither.","Fail startup fast with a clear config check before calling Deno.serve.","Store both PEM paths adjacent in config so they are updated together."],"tags":["https","tls","deno-serve","configuration"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}