denoland/deno · error · RangeError

ERR_CRYPTO_INVALID_SCRYPT_PARAMS

ERR_CRYPTO_INVALID_SCRYPT_PARAMS

Error message

Invalid scrypt params

What it means

Thrown by validateScryptParams in Deno's node:crypto polyfill (ext/node/polyfills/internal/crypto/scrypt.ts:188) when the cost parameter N is less than 2 or not a power of two. scrypt's memory-hard loop requires N = 2^k (k >= 1); any other value (including 0, which falls back to the default first, then odd/custom values) fails with ERR_CRYPTO_INVALID_SCRYPT_PARAMS.

Source

Thrown at ext/node/polyfills/internal/crypto/scrypt.ts:188

      validateInteger(maxmem, "maxmem", 0);
    }
    if (N === 0) N = defaults.N;
    if (r === 0) r = defaults.r;
    if (p === 0) p = defaults.p;
    if (maxmem === 0) maxmem = defaults.maxmem;
  }

  return { password, salt, keylen, N, r, p, maxmem };
}

function validateScryptParams(
  N: number,
  r: number,
  p: number,
  maxmem: number,
) {
  if (N < 2 || (N & (N - 1)) !== 0) {
    throw new ERR_CRYPTO_INVALID_SCRYPT_PARAMS();
  }

  const NBig = BigInt(N);
  const rBig = BigInt(r);
  const pBig = BigInt(p);
  const maxmemBig = BigInt(maxmem);
  const rTimes16 = rBig * 16n;
  if (
    (rTimes16 <= 32n && NBig >= (1n << rTimes16)) ||
    pBig * rBig > ((1n << 30n) - 1n) ||
    128n * NBig * rBig >= maxmemBig
  ) {
    throw new ERR_CRYPTO_INVALID_SCRYPT_PARAMS(
      "error:1C800066:Provider routines::MEMORY_LIMIT_EXCEEDED",
    );
  }
}

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Set N to the nearest power of two for your budget: 16384 (default), 32768, 65536, 1048576.
  2. Compute N as 2 ** Math.floor(Math.log2(budget / (128 * r))) so it stays a power of two.
  3. Keep the (N, r, p) triple from one vetted source rather than hand-tuning each value.

Example fix

// before
crypto.scrypt(pw, salt, 64, { N: 10000, r: 8, p: 1 }, cb);

// after
crypto.scrypt(pw, salt, 64, { N: 16384, r: 8, p: 1 }, cb);
Defensive patterns

Strategy: validation

Validate before calling

const isPow2 = (n) => n >= 2 && (n & (n - 1)) === 0;
if (!isPow2(opts.N)) opts.N = 2 ** Math.round(Math.log2(opts.N));

Type guard

const isValidScryptN = (n) => Number.isInteger(n) && n >= 2 && (n & (n - 1)) === 0;

Try / catch

try { crypto.scrypt(pw, salt, len, opts, cb); } catch (e) { if (e.code === 'ERR_CRYPTO_INVALID_SCRYPT_PARAMS') { opts.N = 1 << Math.round(Math.log2(opts.N)); crypto.scrypt(pw, salt, len, opts, cb); } else throw e; }

Prevention

When it happens

Trigger: crypto.scrypt(pw, salt, 64, { N: 3 }, cb), { N: 10000 }, or { N: 1 }. N must be exactly 2, 4, 8, ... 16384, 1048576, etc.

Common situations: Tuning memory cost with round numbers (10000 instead of 16384); N computed as a memory budget divided by 128*r producing a non-power-of-two; copying N from another KDF's iteration count (e.g. pbkdf2 rounds).

Related errors


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