denoland/deno · error · TypeError

can not create secret key from ${type} key

Error message

can not create secret key from ${type} key

What it means

createSecretKey() throws TypeError 'can not create secret key from <type> key' when the input resolves to a node:crypto KeyObject whose type is 'public' or 'private'. After prepareSecretKey normalizes the input, the polyfill asks the handle for its key type via an internal op and refuses asymmetric material — only buffers, array buffers, and secret KeyObjects are accepted.

Source

Thrown at ext/node/polyfills/internal/crypto/keys.ts:1087

  key: string | ArrayBufferView | ArrayBuffer | KeyObject | CryptoKey,
  encoding?: string,
): KeyObject {
  if (isCryptoKey(key)) {
    if (key.type !== "secret") {
      throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type, "secret");
    }
    return KeyObject.from(key);
  }
  const preparedKey = prepareSecretKey(key, encoding, true);
  if (isArrayBufferView(preparedKey) || isAnyArrayBuffer(preparedKey)) {
    const handle = op_node_create_secret_key(preparedKey);
    return new SecretKeyObject(handle);
  } else {
    const type = op_node_key_type(preparedKey);
    if (type === "secret") {
      return new SecretKeyObject(preparedKey);
    } else {
      throw new TypeError(`can not create secret key from ${type} key`);
    }
  }
}

// Deserializer for KeyObjects transferred via structured clone. Registered
// eagerly (so workers can resurrect a KeyObject before this module loads) from
// `02_register_cloneable.js`; the impl stays lazy here.
function deserializeNodeCryptoKeyObject(data) {
  switch (data.keyType) {
    case "secret": {
      const handle = op_node_create_secret_key(data.keyData);
      return new SecretKeyObject(handle);
    }
    case "public": {
      const handle = op_node_create_public_key(
        data.keyData,
        "der",
        "spki",

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use the key as its own type: public/private KeyObjects already are KeyObjects — return them directly, or use createPublicKey/createPrivateKey for CryptoKeys
  2. Guard with keyObject.type === 'secret' before calling createSecretKey
  3. For derived shared secrets (e.g., ECDH), pass the derived secret buffer (diffieHellman() output), not a key object

Example fix

// before
const ko = createSecretKey(privateKey); // TypeError: can not create secret key from private key

// after
if (input.type === 'secret') {
  ko = createSecretKey(input);
} else {
  ko = input; // already a public/private KeyObject
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (isKeyObject(input)) {
  if (input.type !== 'secret') {
    throw new TypeError(`expected a secret KeyObject, got ${input.type}`);
  }
  return input; // already a secret KeyObject
}
return createSecretKey(input);

Type guard

function isSecretKeyObject(k: unknown): k is KeyObject & { type: 'secret' } {
  return isKeyObject(k) && (k as KeyObject).type === 'secret';
}

Try / catch

try {
  ko = createSecretKey(input);
} catch (e) {
  if (e instanceof TypeError && /can not create secret key from/.test(e.message)) {
    // input was an asymmetric KeyObject: pass it through instead
    ko = input as KeyObject;
  } else throw e;
}

Prevention

When it happens

Trigger: const { privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 }); createSecretKey(privateKey) — the KeyObject type is 'private', so the message reads 'can not create secret key from private key'.

Common situations: Destructured key pairs passed into a helper that expects a shared secret; migration from code that stored everything as Buffers; copying createSecretKey(buffer) patterns with a KeyObject variable swapped in.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/c557f7dd6ec3d060. Report an issue: GitHub.