denoland/deno · error · TypeError

Unsupported 'certFile' / 'keyFile' options provided: use…

Error message

Unsupported 'certFile' / 'keyFile' options provided: use 'cert' / 'key' instead.

What it means

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.

Solutions

  1. Replace `certFile`/`keyFile` with `cert`/`key` containing the PEM text: `cert: await Deno.readText('./cert.pem')`
  2. Inline the PEM strings if managing config outside code
  3. Grep the repo for `certFile` and `keyFile` after upgrading Deno to catch every call site

Example fix

// before
Deno.serve({ port: 443, certFile: './cert.pem', keyFile: './key.pem', handler });

// after
Deno.serve({
  port: 443,
  cert: await Deno.readText('./cert.pem'),
  key: await Deno.readText('./key.pem'),
  handler,
});
Defensive patterns

Strategy: validation

Validate before calling

// Fail fast on legacy keys before calling serve:
for (const legacy of ['certFile', 'keyFile']) {
  if (legacy in opts) {
    throw new Error(`Option '${legacy}' was removed: load the PEM and pass cert/key contents`);
  }
}
Deno.serve(opts);

Prevention

When it happens

Trigger: 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.

Common situations: Upgrading Deno in a project with 1.x-era serve code, tutorials/examples predating the change, shared config objects reused between listenTls and serve.

Related errors


AI-assisted analysis of denoland/deno@abd22074e4 (2026-08-20). Data as JSON: /api/errors/b149d07a213433f1. Report an issue: GitHub.

Appendix: source

Thrown at ext/http/00_serve.ts:1392

              formatHostName(listener.addr.hostname)
            }${additional}`,
          );
        }
      },
      automaticCompression,
    );
  }

  const listenOpts = {
    hostname: options.hostname ?? "0.0.0.0",
    port: options.port ?? 8000,
    reusePort: options.reusePort ?? false,
    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;

View on GitHub (pinned to abd22074e4)