denoland/deno · error · ERR_CRYPTO_UNKNOWN_CIPHER
ERR_CRYPTO_UNKNOWN_CIPHER
ERR_CRYPTO_UNKNOWN_CIPHER
Error message
Unknown cipher
What it means
After confirming cipher is a string, the polyfill checks it against crypto.getCiphers() (ext/node/polyfills/internal/crypto/keygen.ts:334-337) and throws ERR_CRYPTO_UNKNOWN_CIPHER when the name is not in the list. The check is an exact, case-sensitive includes(), so uppercase spellings and aliases not exposed by the OpenSSL build fail just like invented names. Deno's supported set can also differ from a full Node/OpenSSL build.
Source
Thrown at ext/node/polyfills/internal/crypto/keygen.ts:335
}
function parsePrivateKeyEncoding(
enc: any,
keyType: string | undefined,
objName: string,
) {
validateObject(enc, "options");
const { format, type } = parseKeyFormatAndType(enc, keyType, false, objName);
const { cipher, passphrase } = enc;
if (cipher != null) {
if (typeof cipher !== "string") {
throw new ERR_INVALID_ARG_VALUE(option("cipher", objName), cipher);
}
if (!getCiphers().includes(cipher)) {
throw new ERR_CRYPTO_UNKNOWN_CIPHER();
}
if (
format === "der" &&
(type === "pkcs1" || type === "sec1")
) {
throw new ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS(
type,
"does not support encryption",
);
}
} else if (passphrase !== undefined) {
throw new ERR_INVALID_ARG_VALUE(option("cipher", objName), cipher);
}
if (cipher != null && !isStringOrBuffer(passphrase)) {
throw new ERR_INVALID_ARG_VALUE(option("passphrase", objName), passphrase);
}
View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Pick the name from crypto.getCiphers() at runtime - e.g. verify getCiphers().includes(cipher) before generating.
- Use canonical lowercase OpenSSL names such as 'aes-256-cbc' or 'aes-128-gcm'.
- Make the cipher configurable with a safe default so a missing name falls back rather than crashing.
Example fix
// before
privateKeyEncoding: { cipher: 'AES-256-CBC', passphrase: 'pw', /* ... */ } // not in getCiphers()
// after
const cipher = 'aes-256-cbc';
if (!crypto.getCiphers().includes(cipher)) throw new Error(`cipher unavailable: ${cipher}`);
privateKeyEncoding: { cipher, passphrase: 'pw', /* ... */ } Defensive patterns
Strategy: validation
Validate before calling
const cipher = String(cfg.cipher || 'aes-256-cbc');
if (!crypto.getCiphers().includes(cipher)) {
throw new Error(`cipher '${cipher}' unavailable in this runtime; pick from crypto.getCiphers()`);
}
privateKeyEncoding: { format: 'pem', type: 'pkcs8', cipher, passphrase }; Type guard
function isAvailableCipher(name) {
return typeof name === 'string' && crypto.getCiphers().includes(name);
} Try / catch
try { crypto.generateKeyPairSync(alg, opts); }
catch (e) {
if (e.code === 'ERR_CRYPTO_UNKNOWN_CIPHER') {
opts.privateKeyEncoding.cipher = 'aes-256-cbc';
return crypto.generateKeyPairSync(alg, opts);
}
throw e;
} Prevention
- Check membership in crypto.getCiphers() before generating keys.
- Use canonical lowercase OpenSSL cipher names.
- Make the cipher configurable with a known-good default.
When it happens
Trigger: cipher: 'AES-256-CBC' (uppercase, case-sensitive miss); typo like 'aes-256-cbx'; a cipher not compiled into the runtime (e.g. 'des3' variants, 'camellia-256-cbc' depending on build); a cipher name from a different crypto stack (WebCrypto AES-GCM label used verbatim).
Common situations: Cipher names from config files, IaC templates, or documentation that use different casing; hardcoding a legacy cipher the platform dropped; running the same code on Node and Deno where the available cipher lists differ.
Related errors
- ERR_INVALID_ARG_TYPE
- ERR_CRYPTO_UNKNOWN_CIPHER
- ERR_CRYPTO_INVALID_STATE
- Trying to add data in unsupported state
- ERR_UNKNOWN_ENCODING
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/3e0e74d898557126.
Report an issue: GitHub.