{"record":{"id":"b149d07a213433f1","repo":"denoland/deno","slug":"unsupported-certfile-keyfile-options-provide","errorCode":null,"errorMessage":"Unsupported 'certFile' / 'keyFile' options provided: use 'cert' / 'key' instead.","messagePattern":"Unsupported 'certFile' / 'keyFile' options provided: use 'cert' / 'key' instead\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/http/00_serve.ts","lineNumber":1392,"sourceCode":"              formatHostName(listener.addr.hostname)\n            }${additional}`,\n          );\n        }\n      },\n      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;","sourceCodeStart":1374,"sourceCodeEnd":1410,"githubUrl":"https://github.com/denoland/deno/blob/abd22074e47c6a5cd14e9e4e84743f084aa5a575/ext/http/00_serve.ts#L1374-L1410","documentation":"Deno.serve's TLS configuration accepts `cert` and `key` as PEM strings; the older file-path options `certFile`/`keyFile` were removed from this API. serveInner throws this TypeError synchronously if either legacy key is present, so the server never starts. It exists to force migrations to the content-based API instead of silently ignoring TLS settings.","triggerScenarios":"Passing `certFile: './cert.pem', keyFile: './key.pem'` in serve options, copy-pasting config from old Deno examples or from Deno.listenTls code written before the option rename, upgrading a project across Deno versions that dropped the file-path form.","commonSituations":"Upgrading Deno in a project with 1.x-era serve code, tutorials/examples predating the change, shared config objects reused between listenTls and serve.","solutions":["Replace `certFile`/`keyFile` with `cert`/`key` containing the PEM text: `cert: await Deno.readText('./cert.pem')`","Inline the PEM strings if managing config outside code","Grep the repo for `certFile` and `keyFile` after upgrading Deno to catch every call site"],"exampleFix":"// before\nDeno.serve({ port: 443, certFile: './cert.pem', keyFile: './key.pem', handler });\n\n// after\nDeno.serve({\n  port: 443,\n  cert: await Deno.readText('./cert.pem'),\n  key: await Deno.readText('./key.pem'),\n  handler,\n});","handlingStrategy":"validation","validationCode":"// Fail fast on legacy keys before calling serve:\nfor (const legacy of ['certFile', 'keyFile']) {\n  if (legacy in opts) {\n    throw new Error(`Option '${legacy}' was removed: load the PEM and pass cert/key contents`);\n  }\n}\nDeno.serve(opts);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember serve's cert/key take PEM text, not file paths","Grep for certFile/keyFile when upgrading Deno versions","Centralize TLS config loading (readText both PEMs) in one module"],"tags":["http","deno-serve","tls","https","config","migration"],"backgroundTag":"removed-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"}