{"record":{"id":"9e13741383ed0e5a","repo":"denoland/deno","slug":"if-key-is-specified-cert-must-be-specified-as","errorCode":null,"errorMessage":"If `key` is specified, `cert` must be specified as well for `${api}`","messagePattern":"If `key` is specified, `cert` must be specified as well for `(.+?)`","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/net/02_tls.js","lineNumber":153,"sourceCode":"  // TODO(mmastrac): remove this temporary symbol when the API lands\n  if (arguments[1][resolverSymbol] !== undefined) {\n    return createTlsKeyResolver(arguments[1][resolverSymbol]);\n  }\n\n  // Check for \"pem\" format\n  if (keyFormat !== undefined && keyFormat !== \"pem\") {\n    throw new TypeError(\n      `If \"keyFormat\" is specified, it must be \"pem\": received \"${keyFormat}\"`,\n    );\n  }\n\n  if (cert !== undefined && key === undefined) {\n    throw new TypeError(\n      `If \\`cert\\` is specified, \\`key\\` must be specified as well for \\`${api}\\``,\n    );\n  }\n  if (cert === undefined && key !== undefined) {\n    throw new TypeError(\n      `If \\`key\\` is specified, \\`cert\\` must be specified as well for \\`${api}\\``,\n    );\n  }\n\n  if (cert !== undefined) {\n    return op_tls_key_static(cert, key);\n  } else {\n    return op_tls_key_null();\n  }\n}\n\nfunction listenTls({\n  port = 0,\n  hostname = \"0.0.0.0\",\n  transport = \"tcp\",\n  alpnProtocols = undefined,\n  reusePort = false,\n  tcpBacklog = 511,","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/net/02_tls.js#L135-L171","documentation":"The mirror of the cert-without-key check: loadTlsKeyPair throws this TypeError when key is specified but cert is undefined, again naming the API (Deno.connectTls or Deno.listenTls) in the message. The pair requirement is symmetric because a private key alone is not a usable TLS identity.","triggerScenarios":"Deno.listenTls({ port: 443, key }) with no cert; Deno.connectTls({ hostname, port, key: clientKeyPem }) intending mTLS but forgetting the client certificate; env-driven config where the CERT variable is unset while KEY is set.","commonSituations":"Deployment pipelines that inject TLS_KEY but fail to inject TLS_CERT; template configs with one of the two lines deleted; client-certificate setups assembled by hand.","solutions":["Supply the matching certificate string alongside the key","Fail fast at startup: if (!cert || !key) throw new Error('both TLS_CERT and TLS_KEY are required')","For a plain client TLS connection verified only against the server, omit both cert and key"],"exampleFix":"// before\nDeno.listenTls({\n  port: 443,\n  key: Deno.env.get('TLS_KEY'),      // TLS_CERT not set\n  cert: Deno.env.get('TLS_CERT'),\n});\n\n// after\nconst cert = Deno.env.get('TLS_CERT');\nconst key = Deno.env.get('TLS_KEY');\nif (!cert || !key) throw new Error('TLS_CERT and TLS_KEY must both be set');\nDeno.listenTls({ port: 443, cert, key });","handlingStrategy":"validation","validationCode":"const cert = Deno.env.get('TLS_CERT');\nconst key = Deno.env.get('TLS_KEY');\nif ((cert !== undefined) !== (key !== undefined)) {\n  throw new Error('TLS_CERT and TLS_KEY must be set together');\n}","typeGuard":"function hasCompleteKeyPair(o: { cert?: string; key?: string }): o is { cert: string; key: string } {\n  return typeof o.cert === 'string' && typeof o.key === 'string' &&\n    o.cert.length > 0 && o.key.length > 0;\n}","tryCatchPattern":"try {\n  Deno.listenTls(opts);\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes('`cert` must be specified')) {\n    throw new Error('missing TLS_CERT (TLS_KEY was set but no certificate found)');\n  }\n  throw e;\n}","preventionTips":["Fail fast at startup when exactly one of cert/key is configured","Keep cert/key as an atomic pair in config structures, never as independent optional fields","Smoke-test TLS config with a tiny script that calls listenTls before the real server boots"],"tags":["deno","tls","certificate","private-key","typeerror"],"backgroundTag":"tls-certificate-configuration","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}