denoland/deno · error · Error

${name} must be 'an integer' but was ${value}

Error message

${name} must be 'an integer' but was ${value}

What it means

validateIntegerRange in Deno's node internal utils (ext/node/polyfills/_utils.ts:113) throws a plain Error '<name> must be 'an integer' but was <value>' when the value is not an integer (NaN, Infinity, fractional, or numeric strings). Unlike Node's validateInt32/validateInteger, this shim throws uncoded Errors and does not accept string coercion, so values like '1024' fail where Node code may have expected tolerance.

Source

Thrown at ext/node/polyfills/_utils.ts:113

  );
}

function spliceOne(list: string[], index: number) {
  for (; index + 1 < list.length; index++) {
    list[index] = list[index + 1];
  }
  ArrayPrototypePop(list);
}

function validateIntegerRange(
  value: number,
  name: string,
  min = -2147483648,
  max = 2147483647,
) {
  // The defaults for min and max correspond to the limits of 32-bit integers.
  if (!NumberIsInteger(value)) {
    throw new Error(`${name} must be 'an integer' but was ${value}`);
  }

  if (value < min || value > max) {
    throw new Error(
      `${name} must be >= ${min} && <= ${max}. Value was ${value}`,
    );
  }
}

type OptionalSpread<T> = T extends undefined ? []
  : [T];

function once<T = undefined>(
  callback: (...args: OptionalSpread<T>) => void,
) {
  let called = false;
  return function (this: unknown, ...args: OptionalSpread<T>) {
    if (called) return;

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Coerce explicitly and validate before the call: const n = Number(v); if (!Number.isInteger(n)) throw ...
  2. For env/CLI strings, wrap with Number.parseInt(v, 10) and check Number.isNaN first
  3. Round computed sizes with Math.ceil() when fractional values arise from arithmetic

Example fix

// before
stream.readSome({ length: parseInt(maybeUndefined) }); // NaN

// after
const length = Number.parseInt(input, 10);
if (!Number.isInteger(length)) throw new TypeError('length must be an integer');
stream.readSome({ length });
Defensive patterns

Strategy: validation

Validate before calling

const n = Number(value); if (!Number.isInteger(n)) throw new TypeError(`${name} must be an integer`);

Type guard

function isSafeInt(v) { return Number.isInteger(v); }

Try / catch

try { api({ size }); } catch (e) { if (/must be 'an integer'/.test(e.message)) { size = Math.ceil(size); return api({ size }); } throw e; }

Prevention

When it happens

Trigger: Passing 0.5, NaN, or '42' (string) to an option validated by this shim; NaN produced by parseInt(undefined) or a failed Number conversion feeding into a byteLength/position argument.

Common situations: Options parsed from CLI args or env vars without Number() conversion; NaN from Number(null)-adjacent bugs or parseInt of a string without a numeric prefix; fractional sizes from unit-conversion math (KB -> bytes dividing incorrectly).

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/5873f6313dc85732. Report an issue: GitHub.