auth0/node-jsonwebtoken · error
"alg" parameter for "${keyType}" key type must be one of: ${
Error message
"alg" parameter for "${keyType}" key type must be one of: ${allowedAlgorithms.join(', ')}. What it means
When the key's type IS recognized, jsonwebtoken restricts which 'alg' header values may be paired with it (e.g. RS256/RS384/RS512 for 'rsa', ES256/384/512 for 'ec'). Throwing prevents algorithm-confusion attacks where a weak or mismatched algorithm is used with a key of a different family.
Source
Thrown at lib/validateAsymmetricKey.js:29
ES256: 'prime256v1',
ES384: 'secp384r1',
ES512: 'secp521r1',
};
module.exports = function(algorithm, key) {
if (!algorithm || !key) return;
const keyType = key.asymmetricKeyType;
if (!keyType) return;
const allowedAlgorithms = allowedAlgorithmsForKeys[keyType];
if (!allowedAlgorithms) {
throw new Error(`Unknown key type "${keyType}".`);
}
if (!allowedAlgorithms.includes(algorithm)) {
throw new Error(`"alg" parameter for "${keyType}" key type must be one of: ${allowedAlgorithms.join(', ')}.`)
}
/*
* Ignore the next block from test coverage because it gets executed
* conditionally depending on the Node version. Not ignoring it would
* prevent us from reaching the target % of coverage for versions of
* Node under 15.7.0.
*/
/* istanbul ignore next */
if (ASYMMETRIC_KEY_DETAILS_SUPPORTED) {
switch (keyType) {
case 'ec':
const keyCurve = key.asymmetricKeyDetails.namedCurve;
const allowedCurve = allowedCurves[algorithm];
if (keyCurve !== allowedCurve) {
throw new Error(`"alg" parameter "${algorithm}" requires curve "${allowedCurve}".`);
}View on GitHub (pinned to b924272f29)
Solutions
- Match the algorithm to the key type: RSA keys use RS*/PS*, EC keys use ES*, and pass it explicitly in options
- Omit the 'algorithm' option on sign so the library picks the default for the key type
- Regenerate or swap the key to the type the algorithm requires (e.g. generate an RSA key for RS256)
- Check algorithm spelling/case against the allowed list in the error message
Example fix
// before
jwt.sign(payload, ecPrivateKey, { algorithm: 'RS256' });
// after
jwt.sign(payload, ecPrivateKey, { algorithm: 'ES256' }); Defensive patterns
Strategy: validation
Validate before calling
function algFitsKey(alg, key) {
const t = String(key.asymmetricKeyType || '');
const map = { rsa: /^RS/, 'rsa-pss': /^PS/, ec: /^ES/, ed25519: /^EdDSA$/ };
return !t || (map[t] && map[t].test(alg));
}
if (options.algorithm && !algFitsKey(options.algorithm, key)) throw new Error('alg ' + options.algorithm + ' does not match key type ' + key.asymmetricKeyType); Type guard
function isAlgCompatible(alg, key) {
const t = String(key.asymmetricKeyType || '');
if (t === 'rsa') return /^RS(256|384|512)$/.test(alg);
if (t === 'rsa-pss') return /^PS(256|384|512)$/.test(alg);
if (t === 'ec') return /^ES(256|384|512)$/.test(alg);
if (t === 'ed25519') return alg === 'EdDSA';
return true;
} Try / catch
try {
token = jwt.sign(payload, key, { algorithm: requestedAlg });
} catch (err) {
if (/must be one of/.test(err.message)) {
// fall back to the library default for this key type
token = jwt.sign(payload, key);
} else throw err;
} Prevention
- Derive the algorithm from the key type, never hardcode it across environments
- Centralize alg selection in one helper tested per key type
- Watch case: algorithms are uppercase (RS256, not rs256)
- On verify, list algorithms explicitly and keep them consistent with the key in use
When it happens
Trigger: Calling jwt.sign(payload, ecKey, { algorithm: 'RS256' }) or jwt.verify(token, rsaPublicKey, { algorithms: ['ES256'] }) — any combination where the algorithm is not in the allowed list for the detected key type.
Common situations: Copy-pasting sign/verify options between projects that use different key types; typo like 'rs256' (case-sensitive list); reusing an EC key where RSA algorithms are expected after a key rotation.
Related errors
- Unknown key type "${keyType}".
- "alg" parameter "${algorithm}" requires curve "${allowedCurv
- Invalid key for this operation, its RSA-PSS parameters do no
- Invalid key for this operation, its RSA-PSS parameter saltLe
- Expected "${parameterName}" to be a plain object.
AI-assisted analysis of auth0/node-jsonwebtoken@b924272f29 (2026-09-02).
Data as JSON: /api/errors/d38580895e1c18b1.
Report an issue: GitHub.