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

  1. Remove one of the pair — keep N (canonical) and drop cost.
  2. Normalize your options object up front: delete aliases once the canonical key is set.
  3. 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

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


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