denoland/deno · error · TypeError
Invalid key type
Error message
Invalid key type
What it means
prepareKey (cipher.ts:911) throws this TypeError when the key argument is an options object ({ key, encoding, passphrase, format }) but the nested key value is neither string nor binary data. KeyObjects of type 'public'/'private', and { format: 'jwk' } payloads, are handled earlier, so this fires for objects whose key field is the wrong thing — including secret-type KeyObjects, which do not match the public/private branches.
Source
Thrown at ext/node/polyfills/internal/crypto/cipher.ts:911
const data = key.export({ type: "pkcs8", format: "pem" });
return { data: getArrayBufferOrView(data, "key") };
} else if (typeof key == "object") {
const { key: data, encoding, passphrase, format, type } = key;
if (isKeyObject(data)) {
return prepareKey(data);
}
if (format === "jwk") {
// Build a KeyObject from the JWK and export it as PEM so the
// downstream op can consume it via the existing PEM parsing path.
const isPrivate = typeof data === "object" && data !== null &&
typeof (data as { d?: unknown }).d === "string";
const keyObject = isPrivate
? createPrivateKey({ key: data, format: "jwk" })
: createPublicKey({ key: data, format: "jwk" });
return prepareKey(keyObject);
}
if (!isStringOrBuffer(data)) {
throw new TypeError("Invalid key type");
}
// If a passphrase is supplied with raw key material, decrypt the key via
// the native key handle and re-export as unencrypted PKCS#8 PEM so the
// downstream RSA ops can parse it.
if (passphrase != null) {
const keyFormat = format ?? (typeof data === "string" ? "pem" : "der");
const keyData = getArrayBufferOrView(data, "key", encoding);
const passphraseData = getArrayBufferOrView(passphrase, "passphrase");
const handle = op_node_create_private_key(
keyData,
keyFormat,
type ?? "",
passphraseData,
);
const pem = op_node_export_private_key_pem(
handle,
"pkcs8",View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Pass the PEM string or DER Buffer directly, or a KeyObject from createPublicKey/createPrivateKey
- Unwrap nested structures so options.key is the raw key material itself
- For JWK input set format: 'jwk' so the dedicated branch runs
- Never feed secret-type KeyObjects to the RSA encrypt/decrypt functions
Example fix
// before
publicEncrypt({ key: { pem: pemString } }, data); // Invalid key type
// after
publicEncrypt(pemString, data);
// or
publicEncrypt(createPublicKey(pemString), data); Defensive patterns
Strategy: type-guard
Validate before calling
import { isKeyObject } from 'node:crypto';
function isRawKeyMaterial(v) {
return typeof v === 'string' || ArrayBuffer.isView(v) || v instanceof ArrayBuffer;
}
function assertPrepareable(key) {
if (isRawKeyMaterial(key) || isKeyObject(key)) return;
if (key && typeof key === 'object') {
if (isKeyObject(key.key) || key.format === 'jwk' || isRawKeyMaterial(key.key)) return;
}
throw new TypeError('Invalid key type');
} Type guard
function isAcceptableKeyArg(k) {
if (typeof k === 'string' || ArrayBuffer.isView(k) || k instanceof ArrayBuffer) return true;
if (isKeyObject(k) && (k.type === 'public' || k.type === 'private')) return true;
if (k && typeof k === 'object') {
return isKeyObject(k.key) || k.format === 'jwk' || typeof k.key === 'string' || ArrayBuffer.isView(k.key);
}
return false;
} Prevention
- Construct KeyObjects once (createPublicKey/createPrivateKey) and pass those around
- Never double-wrap: options.key must be the key material itself, not a container
- Reject secret-type KeyObjects early on RSA encrypt/decrypt code paths
When it happens
Trigger: publicEncrypt({ key: 123 }, data); publicEncrypt({ key: { pem } }, data) — double-wrapped options; passing a secret KeyObject from createSecretKey() (only 'public'/'private' types are recognized at the top level, and the object branch then finds no usable .key field); a parsed JSON document passed instead of its string field.
Common situations: createSecretKey bytes reused for RSA operations; KMS/JWKS wrappers not unwrapped before use; variable naming where `key` accidentally holds a container rather than the material.
Related errors
- operation not supported for this keytype
- ERR_INVALID_ARG_TYPE
- ERR_OSSL_DH_MODULUS_TOO_SMALL
- ERR_OSSL_DH_BAD_GENERATOR
- ERR_CRYPTO_INVALID_KEYLEN
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/8d0f3c14135a5399.
Report an issue: GitHub.