denoland/deno · error · TypeError

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

Error message

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

What it means

Early Deno 1.x versions configured HTTPS with file-path options certFile/keyFile. Modern Deno.serve reads certificate and key material directly via the cert and key options (PEM string or Uint8Array), so the old path-shaped keys were removed; passing them now throws this TypeError at startup to force the migration instead of silently ignoring TLS.

Source

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

              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 89f33cbef2)

Solutions

  1. Replace certFile/keyFile with cert/key containing the PEM contents: cert: Deno.readTextFileSync('./cert.pem')
  2. Load keys once at startup and pass the strings/Uint8Arrays to serve
  3. Keep permissions in mind: reading the files requires --allow-read

Example fix

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

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

Strategy: validation

Validate before calling

// Migrate legacy options before calling serve
const { certFile, keyFile, ...rest } = options;
if (certFile || keyFile) {
  rest.cert ??= Deno.readTextFileSync(certFile);
  rest.key ??= Deno.readTextFileSync(keyFile);
}
Deno.serve({ ...rest, handler });

Type guard

function hasLegacyTlsOptions(o) {
  return "certFile" in o || "keyFile" in o;
}

Prevention

When it happens

Trigger: Passing certFile: './cert.pem' and/or keyFile: './key.pem' in the serve options object when enabling HTTPS.

Common situations: Upgrading old scripts or deploying tutorials written for early Deno 1.x; copy-pasting TLS config from Node's https.createServer examples adapted to Deno.

Related errors


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