denoland/deno · error · NodeTypeError
ERR_INCOMPATIBLE_OPTION_PAIR
ERR_INCOMPATIBLE_OPTION_PAIR
Error message
Option "N" cannot be used in combination with option "cost"
What it means
Thrown by scrypt/scryptSync in Deno's node:crypto polyfill (ext/node/polyfills/internal/crypto/scrypt.ts:142) when the options object contains both N and its alias cost. They set the same CPU/memory cost parameter, so specifying both is ambiguous and rejected with ERR_INCOMPATIBLE_OPTION_PAIR instead of guessing precedence.
Source
Thrown at ext/node/polyfills/internal/crypto/scrypt.ts:142
r: 8,
p: 1,
maxmem: 32 << 20, // 32 MiB, matches SCRYPT_MAX_MEM.
};
function check(password, salt, keylen, options) {
password = getArrayBufferOrView(password, "password");
salt = getArrayBufferOrView(salt, "salt");
validateInt32(keylen, "keylen", 0);
let { N, r, p, maxmem } = defaults;
if (options && options !== defaults) {
const hasN = options.N !== undefined;
if (hasN) {
N = options.N;
validateUint32(N, "N");
}
if (options.cost !== undefined) {
if (hasN) throw new ERR_INCOMPATIBLE_OPTION_PAIR("N", "cost");
N = options.cost;
validateUint32(N, "cost");
}
const hasR = options.r !== undefined;
if (hasR) {
r = options.r;
validateUint32(r, "r");
}
if (options.blockSize !== undefined) {
if (hasR) throw new ERR_INCOMPATIBLE_OPTION_PAIR("r", "blockSize");
r = options.blockSize;
validateUint32(r, "blockSize");
}
const hasP = options.p !== undefined;
if (hasP) {
p = options.p;
validateUint32(p, "p");
}View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Remove one of the pair — keep N (canonical) and drop cost.
- Normalize your options object up front: delete aliases once the canonical key is set.
- Use a single shared constants object for scrypt parameters to avoid divergent keys.
Example fix
// before
crypto.scrypt(pw, salt, 64, { N: 16384, cost: 16384, r: 8 }, cb);
// after
crypto.scrypt(pw, salt, 64, { N: 16384, r: 8 }, cb); Defensive patterns
Strategy: validation
Validate before calling
if (opts.N !== undefined && opts.cost !== undefined) delete opts.cost; // keep canonical N
Type guard
null
Try / catch
try { crypto.scrypt(pw, salt, len, opts, cb); } catch (e) { if (e.code === 'ERR_INCOMPATIBLE_OPTION_PAIR') { delete opts.cost; crypto.scrypt(pw, salt, len, opts, cb); } else throw e; } Prevention
- Standardize on canonical names N, r, p, maxmem.
- Normalize merged option objects by deleting aliases.
When it happens
Trigger: crypto.scrypt(password, salt, 64, { N: 16384, cost: 16384 }, cb) — both keys present triggers even when values are equal.
Common situations: Merging two config sources (one using N, the other the alias); copy-pasting examples that use different option names; upgrading libraries whose API renamed N to cost while old keys were kept.
Related errors
- ERR_CRYPTO_INVALID_SCRYPT_PARAMS
- ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED
- ERR_INVALID_ARG_TYPE
- ERR_INVALID_ARG_TYPE
- ERR_CRYPTO_UNKNOWN_CIPHER
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/3ea0909915b7c8b7.
Report an issue: GitHub.