paragonie/random_compat · error · TypeError

random_int(): $min must be an integer

Error message

random_int(): $min must be an integer

What it means

random_int() coerces its $min boundary with RandomCompat_intval(); when $min is not integer-representable (fractional float, non-numeric string, object, etc.) it throws this TypeError. The polyfill enforces PHP 7's integer typing for random_int() on PHP 5 hosts.

Solutions

  1. Cast and validate bounds: pass (int) values after confirming they are whole numbers.
  2. Validate user-supplied bounds with filter_var($v, FILTER_VALIDATE_INT).
  3. When decoding JSON, cast numbers explicitly: (int) $decoded['min'].
  4. Ensure callers of wrapper functions pass integer-typed parameters.

Example fix

// before
$roll = random_int($_POST['min'], 6);
// after
$min = filter_var($_POST['min'], FILTER_VALIDATE_INT);
if ($min === false) {
    throw new InvalidArgumentException('min must be an integer');
}
$roll = random_int($min, 6);
Defensive patterns

Strategy: type-guard

Validate before calling

function isValidInt($v): bool {
    return is_int($v) || (is_string($v) && ctype_digit($v));
}

Type guard

function toIntOrNull($v): ?int {
    if (is_int($v)) return $v;
    if (is_float($v) && floor($v) === $v) return (int) $v;
    if (is_string($v) && preg_match('/^-?\d+$/', $v)) return (int) $v;
    return null;
}

Try / catch

try {
    $n = random_int($min, $max);
} catch (TypeError $e) {
    throw new InvalidArgumentException('random_int() bounds must be integers', 0, $e);
}

Prevention

When it happens

Trigger: Calling random_int('1', 10) or random_int(1.5, 10) — RandomCompat_intval($min) throws and lib/random_int.php:57 rethrows as TypeError. The unit tests (testBirthday, testDistribution, testCoverage, testOutput, testRandomRange) exercise this path with invalid types.

Common situations: Range bounds coming from unvalidated user input, JSON-decoded floats (JSON numbers decode as floats), or string values from database rows.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at lib/random_int.php:57

     * @return int
     */
    function random_int($min, $max)
    {
        /**
         * Type and input logic checks
         *
         * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
         * (non-inclusive), it will sanely cast it to an int. If you it's equal to
         * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
         * lose precision, so the <= and => operators might accidentally let a float
         * through.
         */

        try {
            /** @var int $min */
            $min = RandomCompat_intval($min);
        } catch (TypeError $ex) {
            throw new TypeError(
                'random_int(): $min must be an integer'
            );
        }

        try {
            /** @var int $max */
            $max = RandomCompat_intval($max);
        } catch (TypeError $ex) {
            throw new TypeError(
                'random_int(): $max must be an integer'
            );
        }

        /**
         * Now that we've verified our weak typing system has given us an integer,
         * let's validate the logic then we can move forward with generating random
         * integers along a given range.
         */

View on GitHub (pinned to b5d188cc9d)