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
- Cast the upper bound explicitly: random_int(1, (int) $max) after whole-number validation.
- Validate with is_int() or filter_var(..., FILTER_VALIDATE_INT) before the call.
- Normalize decoded values (JSON/config/DB) to ints at the boundary of your application.
- 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
- Cast $max explicitly at call sites; never pass raw config/JSON values.
- Beware float results from arithmetic (PHP 5 division) used as upper bounds.
- Centralize random_int() calls in a validated helper.
- Use PHP 7 scalar type hints so violations surface earlier.
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
- random_bytes(): $bytes must be an integer
- random_bytes(): $bytes must be an integer
- random_int(): $min must be an integer
- RandomCompat_substr(): First argument should be a string
- RandomCompat_strlen() expects a string
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)