yiisoft/yii2 · error · InvalidArgumentException

First parameter ($length) must be an integer

Error message

First parameter ($length) must be an integer

What it means

Security::generateRandomKey() has no parameter type declaration and guards its input manually: is_int($length) fails for strings, floats, and null, throwing InvalidArgumentException before random_bytes() is reached. Numeric-looking values like '32' (string) or 32.0 (float) are rejected because PHP performs no coercion here.

Source

Thrown at framework/base/Security.php:408

        }

        return false;
    }

    /**
     * Generates specified number of random bytes.
     * Note that output may not be ASCII.
     * @see generateRandomString() if you need a string.
     *
     * @param int $length the number of bytes to generate
     * @return string the generated random bytes
     * @throws InvalidArgumentException if wrong length is specified
     * @throws Exception on failure.
     */
    public function generateRandomKey($length = 32)
    {
        if (!is_int($length)) {
            throw new InvalidArgumentException('First parameter ($length) must be an integer');
        }

        if ($length < 1) {
            throw new InvalidArgumentException('First parameter ($length) must be greater than 0');
        }

        return random_bytes($length);
    }

    /**
     * Generates a random string of specified length.
     * The string generated matches [A-Za-z0-9_-]+ and is transparent to URL-encoding.
     *
     * @param int $length the length of the key in characters
     * @return string the generated random key
     * @throws Exception on failure.
     */
    public function generateRandomString($length = 32)

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Cast at the call site: generateRandomKey((int) $size)
  2. Normalize config once at read time so downstream code always sees ints
  3. For nullable sources, coalesce before the call: (int) ($size ?? 32)
  4. Watch for float results of division/multiplication — round or cast explicitly

Example fix

// before
$bytes = Yii::$app->security->generateRandomKey(Yii::$app->params['keyBytes']); // '32' (string) → exception

// after
$bytes = Yii::$app->security->generateRandomKey((int) Yii::$app->params['keyBytes']);
Defensive patterns

Strategy: type-guard

Validate before calling

$length = (int) $length;
if ($length < 1) {
    $length = 32;
}
$bytes = Yii::$app->security->generateRandomKey($length);

Type guard

function isPositiveIntLength($length): bool
{
    return is_int($length) && $length >= 1;
}

Prevention

When it happens

Trigger: Length read from JSON/env/config as a string ('16'); a float produced by arithmetic (16.0 fails is_int); null passed by a wrapper's default instead of relying on the method's own default 32; values forwarded from loosely typed request params.

Common situations: Config-driven key/salt sizes stored as strings; shared helper code mixing strict and loose callers; parameters crossing a JSON boundary and losing their type.

Related errors


AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17). Data as JSON: /api/errors/059e08b8e798177e. Report an issue: GitHub.