denoland/deno · error · ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS
ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS
ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS
Error message
The selected key encoding ${typeStr} can only be used for RSA keys. What it means
In key-pair encoding options, type 'pkcs1' is an RSA-only encoding. parseKeyType (ext/node/polyfills/internal/crypto/keygen.ts:235-244) checks the keyType it was given and, when the pair being generated is anything other than 'rsa', throws ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS ('can only be used for RSA keys'). pkcs1 (RFC 8017) defines RSA public/private key syntax, so this is a structural mismatch, not a preference.
Source
Thrown at ext/node/polyfills/internal/crypto/keygen.ts:240
return "der";
} else if (formatStr === "jwk") {
return "jwk";
}
throw new ERR_INVALID_ARG_VALUE(optionName, formatStr);
}
function parseKeyType(
typeStr: string | undefined,
required: boolean,
keyType: string | undefined,
isPublic: boolean | undefined,
optionName: string,
): string | undefined {
if (typeStr === undefined && !required) {
return undefined;
} else if (typeStr === "pkcs1") {
if (keyType !== undefined && keyType !== "rsa") {
throw new ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS(
typeStr,
"can only be used for RSA keys",
);
}
return "pkcs1";
} else if (typeStr === "spki" && isPublic !== false) {
return "spki";
} else if (typeStr === "pkcs8" && isPublic !== true) {
return "pkcs8";
} else if (typeStr === "sec1" && isPublic !== true) {
if (keyType !== undefined && keyType !== "ec") {
throw new ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS(
typeStr,
"can only be used for EC keys",
);
}
return "sec1";
}View on GitHub (pinned to 9ad36f7a2c)
Solutions
- For EC keys use type 'sec1' (private) / 'spki' (public); for Ed25519 and most private keys use 'pkcs8'.
- Make the encoding type follow the algorithm in config: rsa->pkcs1, ec->sec1, everything else->pkcs8/spki.
- Drop the type option entirely where a safe default exists for your format.
Example fix
// before
crypto.generateKeyPairSync('ed25519', {
privateKeyEncoding: { type: 'pkcs1', format: 'pem' }, // pkcs1 is RSA-only
});
// after
crypto.generateKeyPairSync('ed25519', {
privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
}); Defensive patterns
Strategy: validation
Validate before calling
const PRIVATE_TYPE_BY_ALG = {
rsa: 'pkcs1', 'rsa-pss': 'pkcs8', ec: 'sec1', ed25519: 'pkcs8', dsa: 'pkcs8',
};
const enc = { format: 'pem', type: PRIVATE_TYPE_BY_ALG[alg] };
if (enc.type === 'pkcs1' && alg !== 'rsa') {
throw new Error(`pkcs1 cannot encode ${alg} keys`);
} Type guard
function privateKeyTypeFor(alg) {
if (alg === 'rsa') return 'pkcs1';
if (alg === 'ec') return 'sec1';
return 'pkcs8'; // safe default for ed25519, rsa-pss, dsa, ...
} Try / catch
try {
crypto.generateKeyPairSync(alg, { privateKeyEncoding: { type: 'pkcs1', format: 'pem' } });
} catch (e) {
if (e.code === 'ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS') {
return crypto.generateKeyPairSync(alg, {
privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
});
}
throw e;
} Prevention
- Never reuse one hardcoded encoding block across algorithms.
- Derive encoding type from the algorithm in your config model.
- When unsure, pkcs8/spki accept nearly every key type.
When it happens
Trigger: generateKeyPairSync('ed25519' | 'ec' | 'dsa' | 'rsa-pss', { privateKeyEncoding: { type: 'pkcs1', format: 'pem' } }); reusing an RSA-oriented encoding config for every key type in a multi-algorithm service.
Common situations: Copy-pasting an options block between RSA and EC/Ed25519 generators; config templates with a fixed privateKeyEncoding.type; wrapping generateKeyPairSync behind a generic helper that ignores the algorithm when building encoding options.
Related errors
- ERR_INVALID_ARG_VALUE
- ERR_CRYPTO_UNKNOWN_CIPHER
- ERR_CRYPTO_INVALID_DIGEST
- ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED
- ERR_INVALID_ARG_TYPE
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/e9a9a171de1e7de2.
Report an issue: GitHub.