paragonie/random_compat · error · TypeError

random_bytes(): $bytes must be an integer

Error message

random_bytes(): $bytes must be an integer

What it means

random_compat's libsodium-legacy random_bytes() first coerces its $bytes argument with RandomCompat_intval(); if the value cannot be represented as an integer (floats with fractional parts, non-numeric strings, objects), a TypeError is caught and re-thrown with this message. The library enforces strict integer input even on PHP 5, mirroring PHP 7's random_bytes() signature.

Solutions

  1. Cast the argument explicitly to int before calling: random_bytes((int) $length).
  2. Validate the input is a whole number (is_int() or ctype_digit for strings) before calling.
  3. If the value comes from user input, reject non-numeric input rather than silently casting.
  4. Update code paths that compute lengths with float math to use intval() or (int) casts.

Example fix

// before
$bytes = random_bytes($_GET['length']);
// after
$length = filter_var($_GET['length'], FILTER_VALIDATE_INT);
if ($length === false || $length < 1) {
    throw new InvalidArgumentException('length must be a positive integer');
}
$bytes = random_bytes($length);
Defensive patterns

Strategy: type-guard

Validate before calling

function isValidByteLength($n): bool {
    return is_int($n) && $n >= 1;
}

Type guard

function asByteCount($n): ?int {
    if (is_int($n) && $n >= 1) return $n;
    if (is_string($n) && ctype_digit($n)) return (int) $n;
    return null; // caller must handle
}

Try / catch

try {
    $bytes = random_bytes($length);
} catch (TypeError $e) {
    throw new InvalidArgumentException('$length must be an integer >= 1', 0, $e);
}

Prevention

When it happens

Trigger: Calling random_bytes() with a non-integer value such as '32', 32.5, null, or an array — RandomCompat_intval() throws and lib/random_bytes_libsodium_legacy.php:49 rethrows as TypeError.

Common situations: Passing a string from user input or a config file without casting, passing the result of division on PHP 5 where floats are common, or passing null from an uninitialized variable.

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

Appendix: source

Thrown at lib/random_bytes_libsodium_legacy.php:49

     * If the libsodium PHP extension is loaded, we'll use it above any other
     * solution.
     *
     * libsodium-php project:
     * @ref https://github.com/jedisct1/libsodium-php
     *
     * @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
         */
        $buf = '';

        /**
         * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
         * generated in one invocation.

View on GitHub (pinned to b5d188cc9d)