yiisoft/yii2 · error · InvalidArgumentException

First parameter ($length) must be greater than 0

Error message

First parameter ($length) must be greater than 0

What it means

generateRandomKey() requires $length >= 1 so random_bytes() is never invoked with a zero or negative count. Reaching this exception means an integer 0 or negative value was passed — typically a computed size that legitimately evaluated to 0 (empty input, block-aligned data) rather than a typo.

Source

Thrown at framework/base/Security.php:412

    /**
     * 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)
    {
        if (!is_int($length)) {
            throw new InvalidArgumentException('First parameter ($length) must be an integer');
        }

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Guard computed sizes: max(1, $computed) when at least one byte is acceptable, or skip the call entirely when 0 is the correct answer
  2. Fix operand order in size arithmetic ($total - $used vs $used - $total)
  3. Validate config-driven sizes as >= 1 at bootstrap
  4. Cover the edge lengths (0, 1, boundary) in unit tests for code that computes sizes

Example fix

// before
$padding = $blockSize - (strlen($data) % $blockSize);
$salt = Yii::$app->security->generateRandomKey($padding); // 0 when data is block-aligned → exception

// after
$padding = $blockSize - (strlen($data) % $blockSize);
$salt = $padding >= 1 ? Yii::$app->security->generateRandomKey($padding) : '';
Defensive patterns

Strategy: validation

Validate before calling

$length = (int) $computed;
if ($length < 1) {
    throw new \InvalidArgumentException('Computed random key length must be >= 1, got ' . $computed);
}
$bytes = Yii::$app->security->generateRandomKey($length);

Type guard

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

Prevention

When it happens

Trigger: Padding computed as $blockSize - (strlen($data) % $blockSize) hitting 0 for block-aligned data; generateRandomKey(count($items)) with an empty collection; subtraction with swapped operands yielding a negative; config values defaulting to 0.

Common situations: Cryptographic padding/salt code paths that only fail for certain input lengths; optional inputs where an empty selection produces length 0; off-by-one or operand-order arithmetic bugs.

Related errors


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