{"record":{"id":"a62c7dc287b6db18","repo":"paragonie/random_compat","slug":"random-int-max-must-be-an-integer","errorCode":null,"errorMessage":"random_int(): $max must be an integer","messagePattern":"random_int\\(\\): \\$max must be an integer","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/random_int.php","lineNumber":66,"sourceCode":"         * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats\n         * lose precision, so the <= and => operators might accidentally let a float\n         * through.\n         */\n\n        try {\n            /** @var int $min */\n            $min = RandomCompat_intval($min);\n        } catch (TypeError $ex) {\n            throw new TypeError(\n                'random_int(): $min must be an integer'\n            );\n        }\n\n        try {\n            /** @var int $max */\n            $max = RandomCompat_intval($max);\n        } catch (TypeError $ex) {\n            throw new TypeError(\n                'random_int(): $max must be an integer'\n            );\n        }\n\n        /**\n         * Now that we've verified our weak typing system has given us an integer,\n         * let's validate the logic then we can move forward with generating random\n         * integers along a given range.\n         */\n        if ($min > $max) {\n            throw new Error(\n                'Minimum value must be less than or equal to the maximum value'\n            );\n        }\n\n        if ($max === $min) {\n            return (int) $min;\n        }","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/paragonie/random_compat/blob/b5d188cc9d5e02f94d2c41da23093f1ef557c5b1/lib/random_int.php#L48-L84","documentation":"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.","triggerScenarios":"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.).","commonSituations":"Upper bounds taken from string config values, JSON floats, array count arithmetic producing floats on PHP 5, or null from missing variables.","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."],"exampleFix":"// before\n$idx = random_int(0, count($items) - 1.0);\n// after\n$idx = random_int(0, count($items) - 1);","handlingStrategy":"type-guard","validationCode":"function isValidBound($v): bool {\n    return is_int($v) || (is_string($v) && preg_match('/^-?\\d+$/', $v));\n}","typeGuard":"function toIntBound($v): ?int {\n    if (is_int($v)) return $v;\n    if (is_string($v) && preg_match('/^-?\\d+$/', $v)) return (int) $v;\n    return null;\n}","tryCatchPattern":"try {\n    $n = random_int($min, $max);\n} catch (TypeError $e) {\n    throw new InvalidArgumentException('max must be an integer', 0, $e);\n}","preventionTips":["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."],"tags":["php","typeerror","argument-validation","randomness"],"backgroundTag":"type-mismatch","analyzedSha":"b5d188cc9d5e02f94d2c41da23093f1ef557c5b1","analyzedAt":"2026-09-13T16:12:09.755Z","contentChangedAt":"2026-09-13T16:12:09.755Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}