denoland/deno · error · TypeError
If "keyFormat" is specified, it must be "pem": received
Error message
If "keyFormat" is specified, it must be "pem": received "${keyFormat}" What it means
Deno's TLS key-pair loader (loadTlsKeyPair, used by Deno.connectTls and Deno.listenTls) accepts a keyFormat option, but only the PEM format is implemented: any value other than 'pem' (undefined also means PEM) throws this TypeError. DER and PKCS#12 key material are not supported.
Solutions
- Convert key and certificate to PEM (base64 bodies with BEGIN/END headers) and omit keyFormat
- If specifying the field, use exactly the lowercase string 'pem'
- Generate PEM directly: openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
Example fix
# before: DER material + keyFormat: 'der' openssl rsa -in key.der -inform DER -out key.der # still DER # after: convert to PEM and drop keyFormat openssl rsa -in key.der -inform DER -out key.pem -outform PEM openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM
Defensive patterns
Strategy: validation
Validate before calling
if (keyFormat !== undefined && keyFormat !== 'pem') {
throw new Error(`only PEM keys are supported; convert ${keyFormat} to PEM before calling`);
} Type guard
function isPemFormat(f: unknown): f is 'pem' | undefined {
return f === undefined || f === 'pem';
} Try / catch
try {
await Deno.connectTls({ hostname, port, cert, key, keyFormat });
} catch (e) {
if (e instanceof TypeError && e.message.includes('keyFormat')) {
throw new Error('convert key/cert to PEM and drop keyFormat');
}
throw e;
} Prevention
- Standardize on PEM files (BEGIN/END blocks) for all Deno TLS material
- Omit keyFormat unless a future Deno release documents more formats
- Watch for case: the accepted literal is lowercase 'pem'
When it happens
Trigger: Deno.connectTls({ cert, key, keyFormat: 'der' }); values translated from Node's secure-context options such as 'pkcs8' or 'p12'; config files supplying uppercase 'PEM' (the check is case-sensitive lowercase 'pem').
Common situations: Converting Node tls.createSecureContext options to Deno; keys generated via openssl DER output formats; configuration systems that always populate format fields with a default like 'PEM'.
Related errors
- A key and certificate are required for `Deno.listenTls`
- If `cert` is specified, `key` must be specified as well for
- If `key` is specified, `cert` must be specified as well for
- Unsupported transport
- Dispatcher connect.ca must be a string, Buffer, or…
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/476df96f9ba72659.
Report an issue: GitHub.
Appendix: source
Thrown at ext/net/02_tls.js:142
}
/**
* Loads a TLS keypair from one of the various options. If no key material is provided,
* returns a special Null keypair.
*/
function loadTlsKeyPair(api, {
keyFormat,
cert,
key,
}) {
// TODO(mmastrac): remove this temporary symbol when the API lands
if (arguments[1][resolverSymbol] !== undefined) {
return createTlsKeyResolver(arguments[1][resolverSymbol]);
}
// Check for "pem" format
if (keyFormat !== undefined && keyFormat !== "pem") {
throw new TypeError(
`If "keyFormat" is specified, it must be "pem": received "${keyFormat}"`,
);
}
if (cert !== undefined && key === undefined) {
throw new TypeError(
`If \`cert\` is specified, \`key\` must be specified as well for \`${api}\``,
);
}
if (cert === undefined && key !== undefined) {
throw new TypeError(
`If \`key\` is specified, \`cert\` must be specified as well for \`${api}\``,
);
}
if (cert !== undefined) {
return op_tls_key_static(cert, key);
} else {View on GitHub (pinned to 9ad36f7a2c)