denoland/deno · error · TypeError
Both 'cert' and 'key' must be provided to enable HTTPS
Error message
Both 'cert' and 'key' must be provided to enable HTTPS
What it means
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.
Source
Thrown at ext/http/00_serve.ts:1382
loadBalanced: options[kLoadBalanced] ?? false,
tcpBacklog: options.tcpBacklog,
};
if (options.certFile || options.keyFile) {
throw new TypeError(
"Unsupported 'certFile' / 'keyFile' options provided: use 'cert' / 'key' instead.",
);
}
if (options.alpnProtocols) {
throw new TypeError(
"Unsupported 'alpnProtocols' option provided. 'h2' and 'http/1.1' are automatically supported.",
);
}
let listener;
if (wantsHttps) {
if (!options.cert || !options.key) {
throw new TypeError(
"Both 'cert' and 'key' must be provided to enable HTTPS",
);
}
listenOpts.cert = options.cert;
listenOpts.key = options.key;
listenOpts.alpnProtocols = ["h2", "http/1.1"];
listener = listenTls(listenOpts);
listenOpts.port = listener.addr.port;
} else {
listener = listen(listenOpts);
listenOpts.port = listener.addr.port;
}
const addr = listener.addr;
const onListen = (scheme) => {
if (options.onListen) {
options.onListen(addr);View on GitHub (pinned to 89f33cbef2)
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.
Example fix
// before
const server = Deno.serve({ port: 8443, cert: await Deno.readText("cert.pem") });
// after
const server = Deno.serve({
port: 8443,
cert: await Deno.readText("cert.pem"),
key: await Deno.readText("key.pem"),
}); Defensive patterns
Strategy: validation
Validate before calling
const cert = await Deno.readText("cert.pem");
const key = await Deno.readText("key.pem");
if (!cert || !key) {
throw new Error("TLS requires both a non-empty cert and key PEM");
}
const server = Deno.serve({ port: 8443, cert, key, handler }); Type guard
function hasCompleteTlsPair(o: { cert?: string; key?: string }): boolean {
return Boolean(o.cert) && Boolean(o.key);
} Try / catch
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; } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- Unsupported 'certFile' / 'keyFile' options provided: use 'ce
- ERR_TLS_PROTOCOL_VERSION_CONFLICT
- ERR_TLS_INVALID_PROTOCOL_VERSION
- Cannot create cron job, a unique name is required: received
- Cannot create cron job, a schedule is required: received 'un
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/3b918da2ba8b93dc.
Report an issue: GitHub.