{"record":{"id":"3ea0909915b7c8b7","repo":"denoland/deno","slug":"err-incompatible-option-pair-3ea090","errorCode":"ERR_INCOMPATIBLE_OPTION_PAIR","errorMessage":"Option \"N\" cannot be used in combination with option \"cost\"","messagePattern":"Option \"N\" cannot be used in combination with option \"cost\"","errorType":"exception","errorClass":"NodeTypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/crypto/scrypt.ts","lineNumber":142,"sourceCode":"  r: 8,\n  p: 1,\n  maxmem: 32 << 20, // 32 MiB, matches SCRYPT_MAX_MEM.\n};\n\nfunction check(password, salt, keylen, options) {\n  password = getArrayBufferOrView(password, \"password\");\n  salt = getArrayBufferOrView(salt, \"salt\");\n  validateInt32(keylen, \"keylen\", 0);\n\n  let { N, r, p, maxmem } = defaults;\n  if (options && options !== defaults) {\n    const hasN = options.N !== undefined;\n    if (hasN) {\n      N = options.N;\n      validateUint32(N, \"N\");\n    }\n    if (options.cost !== undefined) {\n      if (hasN) throw new ERR_INCOMPATIBLE_OPTION_PAIR(\"N\", \"cost\");\n      N = options.cost;\n      validateUint32(N, \"cost\");\n    }\n    const hasR = options.r !== undefined;\n    if (hasR) {\n      r = options.r;\n      validateUint32(r, \"r\");\n    }\n    if (options.blockSize !== undefined) {\n      if (hasR) throw new ERR_INCOMPATIBLE_OPTION_PAIR(\"r\", \"blockSize\");\n      r = options.blockSize;\n      validateUint32(r, \"blockSize\");\n    }\n    const hasP = options.p !== undefined;\n    if (hasP) {\n      p = options.p;\n      validateUint32(p, \"p\");\n    }","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/crypto/scrypt.ts#L124-L160","documentation":"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.","triggerScenarios":"crypto.scrypt(password, salt, 64, { N: 16384, cost: 16384 }, cb) — both keys present triggers even when values are equal.","commonSituations":"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.","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."],"exampleFix":"// before\ncrypto.scrypt(pw, salt, 64, { N: 16384, cost: 16384, r: 8 }, cb);\n\n// after\ncrypto.scrypt(pw, salt, 64, { N: 16384, r: 8 }, cb);","handlingStrategy":"validation","validationCode":"if (opts.N !== undefined && opts.cost !== undefined) delete opts.cost; // keep canonical N","typeGuard":"null","tryCatchPattern":"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; }","preventionTips":["Standardize on canonical names N, r, p, maxmem.","Normalize merged option objects by deleting aliases."],"tags":["node-compat","crypto","scrypt","kdf","option-conflict"],"backgroundTag":"incompatible-option-pair","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}