mongodb/laravel-mongodb · error · InvalidArgumentException

Lock lottery must be a couple of integers [$chance, $total]…

Error message

Lock lottery must be a couple of integers [$chance, $total] where $chance <= $total. Example [2, 100]

What it means

MongoLock's constructor validates the optional lottery array used for lock acquisition probabilistics. It must be a two-element array [$chance, $total] of numeric values where the first is <= the second. The library throws InvalidArgumentException in the constructor when the array is malformed, missing elements, or out of order.

Solutions

  1. Fix the 'lottery' value in config/cache.php (or wherever MongoLock is constructed) to a valid [chance, total] pair like [2, 100]
  2. Ensure both elements are numeric (int or numeric string) and present
  3. Ensure chance <= total
  4. Remove the custom 'lottery' option entirely to use the default [2, 100]

Example fix

// before
'lottery' => [200, 100],
// after
'lottery' => [2, 100],
Defensive patterns

Strategy: validation

Validate before calling

$lottery = config('cache.stores.mongodb.lottery', [2, 100]);
assert(is_array($lottery) && count($lottery) === 2 && is_numeric($lottery[0]) && is_numeric($lottery[1]) && $lottery[0] <= $lottery[1]);

Type guard

function isValidLottery(mixed $lottery): bool {
    return is_array($lottery) && count($lottery) === 2
        && is_numeric($lottery[0]) && is_numeric($lottery[1])
        && $lottery[0] <= $lottery[1];
}

Try / catch

try {
    $lock = new MongoCacheRepository($store->lock($name, $seconds));
} catch (InvalidArgumentException $e) {
    Log::error('Invalid lock lottery config', ['message' => $e->getMessage()]);
    $lottery = [2, 100]; // fall back to default
}

Prevention

When it happens

Trigger: Passing a 'lottery' config option to the Mongo cache/lock manager with: a non-numeric element (e.g. ['a', 100]), only one element or none ([2] or []), or chance > total (e.g. [200, 100]). The lottery is read from the cache config when instantiating MongoLock in src/Cache/

Common situations: Typo in cache config where 'lottery' is set to a string or single int; copying Laravel database lock lottery config but inverting the values; user attempting to raise lock-obtainment odds by setting a chance larger than the total.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of mongodb/laravel-mongodb@0634653039 (2026-09-15). Data as JSON: /api/errors/561b528ca6679771. Report an issue: GitHub.

Appendix: source

Thrown at src/Cache/MongoLock.php:35

{
    /**
     * Create a new lock instance.
     *
     * @param Collection      $collection The MongoDB collection
     * @param string          $name       Name of the lock
     * @param int             $seconds    Time-to-live of the lock in seconds
     * @param string|null     $owner      A unique string that identifies the owner. Random if not set
     * @param array{int, int} $lottery    Probability [chance, total] of pruning expired cache items. Set to [0, 0] to disable
     */
    public function __construct(
        private readonly Collection $collection,
        string $name,
        int $seconds,
        ?string $owner = null,
        private readonly array $lottery = [2, 100],
    ) {
        if (! is_numeric($this->lottery[0] ?? null) || ! is_numeric($this->lottery[1] ?? null) || $this->lottery[0] > $this->lottery[1]) {
            throw new InvalidArgumentException('Lock lottery must be a couple of integers [$chance, $total] where $chance <= $total. Example [2, 100]');
        }

        parent::__construct($name, $seconds, $owner);
    }

    /**
     * Attempt to acquire the lock.
     */
    #[Override]
    public function acquire(): bool
    {
        // The lock can be acquired if: it doesn't exist, it has expired,
        // or it is already owned by the same lock instance.
        $isExpiredOrAlreadyOwned = [
            '$or' => [
                ['$lte' => ['$expires_at', $this->getUTCDateTime()]],
                ['$eq' => ['$owner', ['$literal' => $this->owner]]],
            ],

View on GitHub (pinned to 0634653039)