denoland/deno · error · TypeError

Can not create private key from ${type} key

Error message

Can not create private key from ${type} key

What it means

createPrivateKey was handed an existing KeyObject or CryptoKey whose type is not 'private' — it is 'public' or 'secret'. The handle path checks op_node_key_type and throws a TypeError whose message interpolates the actual type, e.g. 'Can not create private key from public key'. Private material cannot be derived from public material, so the request is impossible by construction.

Source

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

      e.message,
      "error:1E08010C:DECODER routines::unsupported",
    )
  ) {
    if (e.library === undefined) e.library = "DECODER routines";
  }
  return err;
}

function createPrivateKey(
  key: any,
): PrivateKeyObject {
  const res = prepareAsymmetricKey(key, kCreatePrivate);
  if (ObjectHasOwn(res, "handle")) {
    const type = op_node_key_type(res.handle);
    if (type === "private") {
      return new PrivateKeyObject(res.handle);
    } else {
      throw new TypeError(`Can not create private key from ${type} key`);
    }
  } else {
    let handle;
    try {
      handle = op_node_create_private_key(
        res.data,
        res.format,
        res.type ?? "",
        res.passphrase,
      );
    } catch (err) {
      throw decorateOsslDecoderError(err);
    }
    return new PrivateKeyObject(handle);
  }
}

function createPublicKey(

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Pass real private material: a PEM/PKCS#8 string, an encrypted PEM plus passphrase, a DER buffer, or a JWK containing 'd'
  2. Load the private key from its own source (-----BEGIN PRIVATE KEY----- file, env var), never from the certificate or public JWK
  3. Store key pairs as { public, private } and pick the right member explicitly
  4. Branch on keyObject.type === 'private' before calling createPrivateKey

Example fix

// before: cert's public key used for signing
const signer = crypto.createPrivateKey(cert.publicKey); // throws TypeError

// after: load the private key material
const signer = crypto.createPrivateKey({
  key: fs.readFileSync('/srv/keys/svc.pem'),
  format: 'pem',
});
Defensive patterns

Strategy: type-guard

Validate before calling

function toPrivateKey(material) {
  if (material && typeof material === 'object' && 'type' in material) {
    if (material.type !== 'private') {
      throw new TypeError(`Need a private key, got ${material.type}`);
    }
    return material; // already a KeyObject
  }
  return crypto.createPrivateKey(material);
}

Type guard

function isPrivateKeyObject(key: unknown): key is crypto.PrivateKeyObject {
  return !!key && typeof key === 'object' &&
    (key as crypto.KeyObject).type === 'private';
}

Try / catch

try {
  return crypto.createPrivateKey(key);
} catch (err) {
  if (err instanceof TypeError && /Can not create private key from/.test(err.message)) {
    throw new Error('Refusing to sign: only public/secret material found. Load the private key file.');
  }
  throw err;
}

Prevention

When it happens

Trigger: crypto.createPrivateKey(publicKeyObject); crypto.createPrivateKey(secretKey); createPrivateKey(cryptoKey) where the CryptoKey was imported from an spki/public JWK source.

Common situations: JWKS verification code selecting the certificate's public key where the private key was expected; loading the TLS cert instead of the key file in a signing service; a variable that was overwritten with the wrong KeyObject earlier in the flow.

Related errors


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