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
- Cast and validate bounds: pass (int) values after confirming they are whole numbers.
- Validate user-supplied bounds with filter_var($v, FILTER_VALIDATE_INT).
- When decoding JSON, cast numbers explicitly: (int) $decoded['min'].
- 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
- Cast both bounds to int after validating, every call site.
- Use filter_var(..., FILTER_VALIDATE_INT) for user input.
- Normalize JSON-decoded numbers with (int) before use.
- Add int type declarations in PHP 7+ wrapper functions.
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
- random_bytes(): $bytes must be an integer
- random_bytes(): $bytes must be an integer
- random_int(): $max 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/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)