denoland/deno · error · ERR_INVALID_ARG_TYPE
ERR_INVALID_ARG_TYPE
ERR_INVALID_ARG_TYPE
Error message
The "ikm" argument must be of type string or an instance of SecretKeyObject, ArrayBuffer, TypedArray, DataView, or Buffer. Received ${key} What it means
prepareKey in ext/node/polyfills/internal/crypto/hkdf.ts accepts an ikm (input keying material) that is a KeyObject, any ArrayBuffer, or something toBuf can convert to a Buffer view (strings, TypedArrays, DataViews). If none of those apply it throws ERR_INVALID_ARG_TYPE listing the accepted shapes. Everything else in hkdf (salt, info) is coerced leniently, but the key must be real key material.
Source
Thrown at ext/node/polyfills/internal/crypto/hkdf.ts:122
info,
length,
};
},
);
function prepareKey(key: any) {
if (isKeyObject(key)) {
return key;
}
if (isAnyArrayBuffer(key)) {
return createSecretKey(new Uint8Array(key as unknown as ArrayBufferLike));
}
key = toBuf(key as string);
if (!isArrayBufferView(key)) {
throw new ERR_INVALID_ARG_TYPE(
"ikm",
[
"string",
"SecretKeyObject",
"ArrayBuffer",
"TypedArray",
"DataView",
"Buffer",
],
key,
);
}
return createSecretKey(key);
}
function hkdf(
hash: string,View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Convert the ikm to a Buffer or string before calling hkdf: Buffer.from(secret).
- If you have a WebCrypto CryptoKey, export it first: crypto.subtle.exportKey('raw', key) then pass the ArrayBuffer.
- If you hold a JWK, rebuild a KeyObject with crypto.createSecretKey(Buffer.from(jwk.k, 'base64url')) instead of passing the JWK itself.
- Add a type check at your own API boundary so bad values fail with your error message.
Example fix
// before
crypto.hkdfSync('sha256', 12345, salt, info, 32); // number ikm -> ERR_INVALID_ARG_TYPE
// after
crypto.hkdfSync('sha256', '12345', salt, info, 32); // string
crypto.hkdfSync('sha256', Buffer.from('12345'), salt, info, 32); // or Buffer Defensive patterns
Strategy: type-guard
Validate before calling
function assertIkm(key) {
const ok = typeof key === 'string' || Buffer.isBuffer(key) ||
ArrayBuffer.isView(key) || key instanceof ArrayBuffer ||
(key && typeof key === 'object' && key.constructor?.name === 'KeyObject');
if (!ok) throw new TypeError('hkdf key must be string/Buffer/TypedArray/ArrayBuffer/KeyObject');
}
assertIkm(ikm);
crypto.hkdfSync('sha256', ikm, salt, info, 32); Type guard
function isHkdfKeyMaterial(v) {
return typeof v === 'string' || ArrayBuffer.isView(v) ||
v instanceof ArrayBuffer || crypto.KeyObject?.isKeyObject?.(v) === true;
} Try / catch
try {
crypto.hkdfSync('sha256', ikm, salt, info, 32);
} catch (e) {
if (e.code === 'ERR_INVALID_ARG_TYPE' && /ikm/.test(e.message)) {
throw new TypeError(`bad ikm from source X (${typeof ikm})`);
}
throw e;
} Prevention
- Coerce secrets to Buffer at the edge: ikm = Buffer.from(ikm).
- Export WebCrypto CryptoKeys via subtle.exportKey before feeding node:crypto hkdf.
- Type-check values coming from JSON/env before passing them as key material.
When it happens
Trigger: crypto.hkdfSync('sha256', 12345, salt, info, 32) (number); passing null/undefined, a plain object, or a boolean as key; passing a KeyObject-like wrapper (e.g. a JWK object or {k: '...'}) that is not an actual KeyObject.
Common situations: Reading a passphrase from an env var or JSON config and forgetting to convert it to string/Buffer; passing a parsed JWK where a SecretKeyObject is expected; passing a CryptoKey (WebCrypto object, not a Node KeyObject) into node:crypto hkdf.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- ERR_OUT_OF_RANGE
- ERR_CRYPTO_INVALID_KEYLEN
- ERR_CRYPTO_INVALID_DIGEST
- HKDF keys are not extractable
- Unsupported key usage for an HKDF key
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/66c1e89fdf765147.
Report an issue: GitHub.