paragonie/random_compat · error · TypeError

random_int(): $max must be an integer

Error message

random_int(): $max must be an integer

What it means

random_int() coerces its $max boundary with RandomCompat_intval() and throws this TypeError when $max is not integer-representable. It enforces the same strict integer contract PHP 7 applies to random_int(), regardless of backend.

Solutions

  1. Cast the upper bound explicitly: random_int(1, (int) $max) after whole-number validation.
  2. Validate with is_int() or filter_var(..., FILTER_VALIDATE_INT) before the call.
  3. Normalize decoded values (JSON/config/DB) to ints at the boundary of your application.
  4. Add parameter type declarations (int) in PHP 7+ wrappers to catch mistakes early.

Example fix

// before
$idx = random_int(0, count($items) - 1.0);
// after
$idx = random_int(0, count($items) - 1);
Defensive patterns

Strategy: type-guard

Validate before calling

function isValidBound($v): bool {
    return is_int($v) || (is_string($v) && preg_match('/^-?\d+$/', $v));
}

Type guard

function toIntBound($v): ?int {
    if (is_int($v)) return $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('max must be an integer', 0, $e);
}

Prevention

When it happens

Trigger: Calling random_int(1, '10') or random_int(1, 10.5) — RandomCompat_intval($max) throws and lib/random_int.php:66 rethrows TypeError. Covered by the library's own test suite (testBirthday, testDistribution, etc.).

Common situations: Upper bounds taken from string config values, JSON floats, array count arithmetic producing floats on PHP 5, or null from missing variables.

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/a62c7dc287b6db18. Report an issue: GitHub.

Appendix: source

Thrown at lib/random_int.php:66

         * ~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.
         */
        if ($min > $max) {
            throw new Error(
                'Minimum value must be less than or equal to the maximum value'
            );
        }

        if ($max === $min) {
            return (int) $min;
        }

View on GitHub (pinned to b5d188cc9d)