paragonie/random_compat · error · TypeError

Expected an integer.

Error message

Expected an integer.

What it means

RandomCompat_intval() is the library's strict integer coercion helper. After attempting casts (floats, numeric strings, objects with known representations), if the value still is not an int and $fail_open is false, it throws a TypeError('Expected an integer.'). It guards random_int() and internal callers against non-integer inputs.

Solutions

  1. Validate and cast bounds before the call: random_int((int) $min, (int) $max) — only after confirming the value is genuinely numeric.
  2. Use is_int()/is_numeric() checks on inputs from HTTP/JSON sources and reject non-integers with a 400-style response.
  3. If you intended float math, use a non-cryptographic function instead; random_int only accepts integers.

Example fix

// before
$n = random_int($_GET['min'], $_GET['max']);

// after
$min = filter_var($_GET['min'], FILTER_VALIDATE_INT);
$max = filter_var($_GET['max'], FILTER_VALIDATE_INT);
if ($min === false || $max === false) {
    throw new InvalidArgumentException('min/max must be integers');
}
$n = random_int($min, $max);
Defensive patterns

Strategy: validation

Validate before calling

// before calling random_int
$min = filter_var($rawMin, FILTER_VALIDATE_INT);
$max = filter_var($rawMax, FILTER_VALIDATE_INT);
if ($min === false || $max === false || $min > $max) {
    throw new InvalidArgumentException('Bounds must be integers with min <= max');
}

Type guard

function asIntOrNull($value) {
    if (is_int($value)) return $value;
    if (is_string($value) && preg_match('/^-?\d+$/', $value)) return (int) $value;
    return null;
}

Try / catch

try {
    $n = random_int($min, $max);
} catch (TypeError $e) {
    // input was not an integer: reject the request, do not retry blindly
    throw new InvalidArgumentException('random_int bounds must be integers', 0, $e);
} catch (Exception $e) {
    // entropy source failure — handle separately
}

Prevention

When it happens

Trigger: Calling random_int($min, $max) with arguments that cannot be losslessly interpreted as integers: non-numeric strings ('abc'), floats with fractional parts (1.5), true/false, arrays, null, or objects; also passing values exceeding the integer size limits that fail the strict conversion.

Common situations: Bounds sourced from user input ($_GET['min']), JSON-decoded values that are strings, database BIGINT columns returned as strings on PHP 5, or accidental use of a float constant like M_PI as a bound.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of paragonie/random_compat@b5d188cc9d (2026-09-13). Data as JSON: /api/errors/92a90f4443a4eb14. Report an issue: GitHub.

Appendix: source

Thrown at lib/cast_to_int.php:71

            /** @psalm-suppress InvalidOperand */
            $number += 0;
        }
        /** @var int|float $number */

        if (
            is_float($number)
                &&
            $number > ~PHP_INT_MAX
                &&
            $number < PHP_INT_MAX
        ) {
            $number = (int) $number;
        }

        if (is_int($number)) {
            return (int) $number;
        } elseif (!$fail_open) {
            throw new TypeError(
                'Expected an integer.'
            );
        }
        return $number;
    }
}

View on GitHub (pinned to b5d188cc9d)