paragonie/random_compat · error · TypeError

random_bytes(): $bytes must be an integer

Error message

random_bytes(): $bytes must be an integer

What it means

The mcrypt-backed random_bytes() coerces $bytes with RandomCompat_intval() and rethrows a TypeError when the argument is not integer-representable. This keeps the polyfill's behavior aligned with PHP 7's strict random_bytes() typing even on PHP 5 hosts using mcrypt_create_iv().

Solutions

  1. Cast explicitly: random_bytes((int) $length) after verifying the value is a whole number.
  2. Use is_int() / ctype_digit() validation before the call.
  3. Sanitize user-supplied lengths with filter_var(..., FILTER_VALIDATE_INT).
  4. Audit call sites where the length comes from arithmetic that can produce floats.

Example fix

// before
$key = random_bytes($payload['size']);
// after
$size = (int) $payload['size'];
if ($size < 1 || (string) $size !== (string) $payload['size']) {
    throw new InvalidArgumentException('size must be an integer >= 1');
}
$key = random_bytes($size);
Defensive patterns

Strategy: type-guard

Validate before calling

function isValidLength($n): bool {
    return is_int($n) || (is_string($n) && ctype_digit($n));
}

Type guard

function toIntLen($n): ?int {
    if (is_int($n)) return $n;
    if (is_string($n) && preg_match('/^\d+$/', $n)) return (int) $n;
    return null;
}

Try / catch

try {
    $buf = random_bytes($size);
} catch (TypeError $e) {
    throw new InvalidArgumentException('size must be an integer', 0, $e);
}

Prevention

When it happens

Trigger: Passing a float with a fractional part, numeric string, null, array, or object to random_bytes() on a system where the mcrypt backend is active — RandomCompat_intval() throws and lib/random_bytes_mcrypt.php:48 rethrows TypeError.

Common situations: Uncast values from query strings or JSON bodies, float results of arithmetic on PHP 5, or passing a DateTime/other object where a byte count was intended.

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

Appendix: source

Thrown at lib/random_bytes_mcrypt.php:48

    /**
     * Powered by ext/mcrypt (and thankfully NOT libmcrypt)
     *
     * @ref https://bugs.php.net/bug.php?id=55169
     * @ref https://github.com/php/php-src/blob/c568ffe5171d942161fc8dda066bce844bdef676/ext/mcrypt/mcrypt.c#L1321-L1386
     *
     * @param int $bytes
     *
     * @throws Exception
     *
     * @return string
     */
    function random_bytes($bytes)
    {
        try {
            /** @var int $bytes */
            $bytes = RandomCompat_intval($bytes);
        } catch (TypeError $ex) {
            throw new TypeError(
                'random_bytes(): $bytes must be an integer'
            );
        }

        if ($bytes < 1) {
            throw new Error(
                'Length must be greater than 0'
            );
        }

        /** @var string|bool $buf */
        $buf = @mcrypt_create_iv((int) $bytes, (int) MCRYPT_DEV_URANDOM);
        if (
            is_string($buf)
                &&
            RandomCompat_strlen($buf) === $bytes
        ) {
            /**

View on GitHub (pinned to b5d188cc9d)