denoland/deno · error · NodeRangeError

ERR_OUT_OF_RANGE

ERR_OUT_OF_RANGE

Error message

The value of "iterations" is out of range. It must be <= ${MAX_I32}. Received ${iterations}

What it means

pbkdf2's argument checker (check() in ext/node/polyfills/internal/crypto/pbkdf2.ts) throws ERR_OUT_OF_RANGE when 'iterations' exceeds 2147483647 (2^31-1). iterations is first validated as a positive uint32, then explicitly capped at the signed 32-bit limit used by the native PBKDF2 implementation. Values above it cannot be passed to the underlying crypto library at all.

Source

Thrown at ext/node/polyfills/internal/crypto/pbkdf2.ts:61

const MAX_ALLOC = MathPow(2, 30) - 1;
const MAX_I32 = 2 ** 31 - 1;

function check(
  password: any,
  salt: any,
  iterations: number,
  keylen: number,
  digest: string,
) {
  validateString(digest, "digest");
  password = getArrayBufferOrView(password, "password", "buffer");
  salt = getArrayBufferOrView(salt, "salt", "buffer");
  validateUint32(iterations, "iterations", true);
  validateUint32(keylen, "keylen");

  if (iterations > MAX_I32) {
    throw new ERR_OUT_OF_RANGE("iterations", `<= ${MAX_I32}`, iterations);
  }

  if (keylen > MAX_I32) {
    throw new ERR_OUT_OF_RANGE("keylen", `<= ${MAX_I32}`, keylen);
  }

  return { password, salt, iterations, keylen, digest };
}

/**
 * @param iterations Needs to be higher or equal than zero
 * @param keylen  Needs to be higher or equal than zero but less than max allocation size (2^30)
 * @param digest Algorithm to be used for encryption
 */
function pbkdf2Sync(
  password: any,
  salt: any,
  iterations: number,

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use a realistic iteration count, e.g., 100,000-600,000 for PBKDF2-SHA256 per current OWASP guidance
  2. Clamp and validate iterations <= 2147483647 before calling pbkdf2
  3. If you genuinely need more key stretching, switch to scrypt or argon2 rather than pushing iterations past the cap

Example fix

// before
const iterations = Number(cfg.iterations); // 3_000_000_000 from config
crypto.pbkdf2Sync(pw, salt, iterations, 32, 'sha256'); // throws

// after
const iterations = Math.min(Number(cfg.iterations), 600_000);
crypto.pbkdf2Sync(pw, salt, iterations, 32, 'sha256');
Defensive patterns

Strategy: validation

Validate before calling

const MAX_I32 = 2 ** 31 - 1;
if (!Number.isInteger(iterations) || iterations <= 0 || iterations > MAX_I32) {
  throw new RangeError(`iterations must be an integer in (0, ${MAX_I32}]`);
}
crypto.pbkdf2Sync(password, salt, iterations, keylen, digest);

Type guard

const isValidPbkdf2Iterations = (n: unknown): n is number =>
  typeof n === 'number' && Number.isInteger(n) && n > 0 && n <= 2 ** 31 - 1;

Try / catch

try {
  crypto.pbkdf2Sync(password, salt, iterations, keylen, digest);
} catch (e) {
  if (e?.code === 'ERR_OUT_OF_RANGE' && /iterations/.test(e.message)) {
    throw new Error(`refusing absurd iterations=${iterations}; check config`);
  } else throw e;
}

Prevention

When it happens

Trigger: crypto.pbkdf2Sync(password, salt, 3_000_000_000, 32, 'sha256') — any iterations value greater than MAX_I32, including via the async crypto.pbkdf2 form.

Common situations: Security-policy numbers translated with a wrong multiplier (600k read as 600,000,000); iterations parsed from config with a stray unit or extra digit; benchmark scripts cranking iteration counts to extremes.

Related errors


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