denoland/deno · error · TypeError
ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE
ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE
Error message
Invalid key object type ${key.type}, expected private. What it means
getKeyObjectHandle validates a KeyObject against the operation context. For contexts that require a private key — kConsumePrivate (crypto.sign, the private side of DiffieHellman) and kCreatePublic (crypto.createPublicKey) — a KeyObject whose type is not 'private' throws ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE reporting the actual type and 'expected private'.
Source
Thrown at ext/node/polyfills/internal/crypto/keys.ts:231
// @ts-expect-error __proto__ is magic
__proto__: null,
configurable: true,
value: "KeyObject",
},
});
function getKeyObjectHandle(key: KeyObject, ctx: number) {
if (ctx === kCreatePrivate) {
throw new ERR_INVALID_ARG_TYPE(
"key",
["string", "ArrayBuffer", "Buffer", "TypedArray", "DataView"],
key,
);
}
if (key.type !== "private") {
if (ctx === kConsumePrivate || ctx === kCreatePublic) {
throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type, "private");
}
if (key.type !== "public") {
throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(
key.type,
"private or public",
);
}
}
return key[kHandle];
}
function getKeyObjectHandleFromJwk(key, ctx) {
validateObject(key, "key");
validateOneOf(
key.kty,
"key.kty",
["RSA", "EC", "OKP"],View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Pass the private KeyObject to sign/derive operations; check key.type === 'private' when arguments come from elsewhere
- For createPublicKey on a KeyObject, use the existing public KeyObject directly instead of re-wrapping
- In shared helpers, branch on the input being a KeyObject vs raw PEM before calling factories
Example fix
// before const sig = crypto.sign(null, data, publicKeyObject); // after const sig = crypto.sign(null, data, privateKeyObject);
Defensive patterns
Strategy: validation
Validate before calling
function requirePrivateKey(key) {
if (!crypto.isKeyObject(key) || key.type !== 'private') {
throw new Error(`Expected private KeyObject, got ${key?.type ?? typeof key}`);
}
return key;
}
crypto.sign(null, data, requirePrivateKey(signingKey)); Type guard
function isPrivateKeyObject(k) {
return crypto.isKeyObject(k) && k.type === 'private';
} Try / catch
try {
return crypto.sign(null, data, key);
} catch (e) {
if (e.code === 'ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE') throw new Error(`Wrong key kind for this op: ${e.message}`);
throw e;
} Prevention
- Name variables privateKey/publicKey explicitly to avoid swaps
- Check key.type before asymmetric operations
- Do not re-wrap public KeyObjects with createPublicKey in portable code
When it happens
Trigger: crypto.sign(null, data, publicKeyObject); dh.computeSecret(publicKeyObject, privateKeyObject) with the arguments swapped; crypto.createPublicKey(publicKeyObject) — Deno throws where Node tolerantly returns the same key.
Common situations: Swapped arguments in diffiehellman.computeSecret; signing with the public key of a pair (PEM mix-ups); re-wrapping a public KeyObject via createPublicKey, a pattern that works on Node but not in the polyfill.
Related errors
- ERR_INVALID_ARG_VALUE
- Can not create private key from ${type} key
- can not create secret key from ${type} key
- Unsupported KeyObject type for structured clone: ${data.keyT
- ERR_INVALID_ARG_VALUE
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/cfef32034f9ada4e.
Report an issue: GitHub.