TheAlgorithms/JavaScript · error · Error

Rule must be an integer between the values 0 and 255 (got ${

Error message

Rule must be an integer between the values 0 and 255 (got ${rule})

What it means

Thrown by getNextElementaryGeneration when the rule is not an integer. Elementary cellular automata rules are defined by an 8-bit lookup table indexed 0..255, so a fractional/string/NaN rule cannot map to a deterministic rule table. This is the type guard (Error); the range check at line 78 is separate.

Source

Thrown at Cellular-Automata/Elementary.js:73

 * 000000001101010101010101010101010101010101011000000      000000001100110000000000000000000000000110011000000
 * 000000011101010101010101010101010101010101011100000      000000011111111000000000000000000000001111111100000
 *
 * DEV NOTE: This implementation assumes that cells on the edge (who only have 1 neighbor) have 1 neighbor and a permanently "dead" neighbor, which is technically correct in a finite space. However, most diagrams of these elementary cellular automata rules assume a infinite line of cells. Therefore, the edges of the array may not evolve perfectly in line with pictured diagrams which assume infinite space.
 */

/**
 * Find the next Elementary Cell Automata Generation given the previous generation and the rule [0-255] to follow
 * @param {(0 | 1)[]} generation The current generation of the Elementary Cellular Automata simulation
 * @param {number} rule The current rule of the Elementary Cellular Automata simulation. Must be an integer between 0 and 255 inclusive
 * @returns {(0 | 1)[]} The next generation according to the inputted rule
 */
export function getNextElementaryGeneration(generation, rule) {
  const NUM_ELEMENTARY_NEIGHBORHOOD_STATES = 8
  const MIN_RULE = 0
  const MAX_RULE = 255

  if (!Number.isInteger(rule)) {
    throw new Error(
      `Rule must be an integer between the values 0 and 255 (got ${rule})`
    )
  }
  if (rule < MIN_RULE || rule > MAX_RULE) {
    throw new RangeError(
      `Rule must be an integer between the values 0 and 255 (got ${rule})`
    )
  }

  const binaryRule = rule
    .toString(2)
    .padStart(NUM_ELEMENTARY_NEIGHBORHOOD_STATES, '0')
  const ruleData = binaryRule.split('').map((bit) => Number.parseInt(bit)) // note that ruleData[0] represents "all alive" while ruleData[7] represents "all dead"
  const output = new Array(generation.length)
  const LEFT_DEAD = 4 // 100 in binary
  const MIDDLE_DEAD = 2 // 010 in binary
  const RIGHT_DEAD = 1 // 001 in binary

View on GitHub (pinned to 5c39e87a9a)

Solutions

  1. Pass an integer literal: getNextElementaryGeneration(gen, 30).
  2. Parse strings explicitly: Math.trunc(Number(raw)) and confirm it is an integer.
  3. Guard untrusted input with Number.isInteger(rule) before calling.

Example fix

// before
getNextElementaryGeneration(gen, params.rule) // string from query
// after
const rule = Math.trunc(Number(params.rule))
if (Number.isInteger(rule)) getNextElementaryGeneration(gen, rule)
Defensive patterns

Strategy: type-guard

Validate before calling

function nextGenSafe(gen, rule) {
  const r = Math.trunc(Number(rule));
  if (!Number.isInteger(r)) throw new Error('Rule must be an integer');
  return getNextElementaryGeneration(gen, r);
}

Type guard

/** @param {unknown} r @returns {r is number} */
const isIntRule = r => Number.isInteger(r);

Try / catch

try { return getNextElementaryGeneration(gen, rule); }
catch (e) {
  if (/integer between the values 0 and 255/.test(e.message) && !Number.isInteger(rule)) {
    return getNextElementaryGeneration(gen, Math.trunc(Number(rule)));
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a float (e.g. 30.5), a numeric string ("30"), NaN, undefined, or any value failing Number.isInteger.

Common situations: Reading the rule from user input or a URL query param (always a string), or applying a parseFloat that introduced a fraction.

Related errors


AI-assisted analysis of TheAlgorithms/JavaScript@5c39e87a9a (2026-08-13). Data as JSON: /api/errors/c1e588df9a27ec9e. Report an issue: GitHub.