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_bytes() first coerces its argument with RandomCompat_intval(), which throws TypeError for values that cannot be losslessly converted to a non-negative-safe integer (floats with fractions, non-numeric strings, objects, arrays, null). The library catches that internal TypeError and rethrows a clearer one so the caller knows the $bytes parameter itself is bad. This is a fail-fast contract check mirroring PHP 7's native random_bytes() signature.

Solutions

  1. Cast or validate the length to a positive integer before calling: $len = (int) $len;
  2. Add a type guard: if (!is_int($len) || $len < 1) { throw new InvalidArgumentException(...); }
  3. Use RandomCompat_intval() or PHP's is_int()/ctype_digit() checks on any dynamic input.
  4. Pass a literal integer constant for fixed sizes (e.g. random_bytes(32)).

Example fix

// before
$token = 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');
}
$token = random_bytes($length);
Defensive patterns

Strategy: type-guard

Validate before calling

function ensureRandomLength($len) {
    if (!is_int($len) || $len < 1) {
        throw new InvalidArgumentException('random_bytes length must be a positive integer');
    }
    return $len;
}

Type guard

function isValidRandomLength($len) {
    return is_int($len) && $len >= 1;
}

Try / catch

try {
    $bytes = random_bytes($len);
} catch (TypeError $e) {
    // $len was not an integer; log and fail the request
    throw new InvalidArgumentException('invalid random_bytes length', 0, $e);
}

Prevention

When it happens

Trigger: Calling random_bytes() with a non-integer value: a numeric string like '10' in strict setups that fail intval conversion, a float such as 10.5, null, a boolean, an array, or an object lacking a valid __toString/to-int path that RandomCompat_intval() rejects.

Common situations: Passing user-supplied request input or unvalidated JSON/GET/POST values straight into random_bytes(); forwarding the result of a calculation that returned null on failure; PHP 5.x polyfill usage where no native type declarations protect the call site.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of paragonie/random_compat@b5d188cc9d (2026-09-13). Data as JSON: /api/errors/e40f32a75e789801. Report an issue: GitHub.

Appendix: source

Thrown at lib/random_bytes_com_dotnet.php:47

if (!is_callable('random_bytes')) {
    /**
     * Windows with PHP < 5.3.0 will not have the function
     * openssl_random_pseudo_bytes() available, so let's use
     * CAPICOM to work around this deficiency.
     *
     * @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 */
        $buf = '';
        if (!class_exists('COM')) {
            throw new Error(
                'COM does not exist'
            );
        }
        /** @var COM $util */

View on GitHub (pinned to b5d188cc9d)