{"record":{"id":"04e9c28e7147d10f","repo":"laravel/framework","slug":"this-cache-store-does-not-support-locks-04e9c2","errorCode":null,"errorMessage":"This cache store does not support locks.","messagePattern":"This cache store does not support locks\\.","errorType":"exception","errorClass":"BadMethodCallException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Cache/Repository.php","lineNumber":742,"sourceCode":"     * @return TReturn\n     *\n     * @throws \\Illuminate\\Contracts\\Cache\\LockTimeoutException\n     */\n    public function withoutOverlapping($key, callable $callback, $lockFor = 0, $waitFor = 10, $owner = null)\n    {\n        return $this->store->lock(enum_value($key), $lockFor, $owner)->block($waitFor, $callback);\n    }\n\n    /**\n     * Funnel a callback for a maximum number of simultaneous executions.\n     *\n     * @param  \\UnitEnum|string  $name\n     * @return \\Illuminate\\Cache\\Limiters\\ConcurrencyLimiterBuilder\n     */\n    public function funnel($name)\n    {\n        if (! $this->store instanceof LockProvider) {\n            throw new BadMethodCallException('This cache store does not support locks.');\n        }\n\n        return new ConcurrencyLimiterBuilder($this, enum_value($name));\n    }\n\n    /**\n     * Remove an item from the cache.\n     *\n     * @param  \\UnitEnum|array|string  $key\n     * @return bool\n     */\n    public function forget($key)\n    {\n        $key = enum_value($key);\n\n        $this->event(new ForgettingKey($this->getName(), $key));\n\n        return tap($this->store->forget($this->itemKey($key)), function ($result) use ($key) {","sourceCodeStart":724,"sourceCodeEnd":760,"githubUrl":"https://github.com/laravel/framework/blob/e0f6eb3518ac29fbbca8529e97d0df7fc9f24481/src/Illuminate/Cache/Repository.php#L724-L760","documentation":"Thrown by Repository::funnel() when the underlying cache store does not implement Illuminate\\Contracts\\Cache\\LockProvider. Funneling requires distributed locks, so stores like 'array', 'file' (depending on version), 'dynamodb', or custom stores that omit LockProvider cannot back it.","triggerScenarios":"Calling Cache::funnel('name')->limit(...) while the configured CACHE_STORE is one without lock support (commonly 'array' in tests, or 'file').","commonSituations":"Running queue/concurrency-limited code in the testing environment with CACHE_STORE=array; deploying to a host where redis/memcached/database is not configured; misconfigured CACHE_DRIVER.","solutions":["Switch CACHE_STORE to a LockProvider-backed store: redis, memcached, database, or dynamodb where supported.","In tests, use a store that supports locks (e.g. database/sqlite with the lock schema) rather than 'array'.","If you must support non-lock stores, branch on $cache->getStore() instanceof LockProvider before calling funnel()."],"exampleFix":"// before (tests/.env or phpunit.xml)\nCACHE_STORE=array\n// after\nCACHE_STORE=database","handlingStrategy":"type-guard","validationCode":"if (Cache::getStore() instanceof \\Illuminate\\Contracts\\Cache\\LockProvider) {\n    Cache::funnel('job')->limit(1)->block(5)->then(fn () => doWork());\n} else {\n    // fallback: run without funneling\n    doWork();\n}","typeGuard":"function storeSupportsLocks(\\Illuminate\\Contracts\\Cache\\Store $store): bool {\n    return $store instanceof \\Illuminate\\Contracts\\Cache\\LockProvider;\n}","tryCatchPattern":"try {\n    Cache::funnel('name')->limit(1)->then($callback);\n} catch (\\BadMethodCallException $e) {\n    // store lacks locks; degrade gracefully\n    $callback();\n}","preventionTips":["Use redis/memcached/database as CACHE_STORE in production for concurrency features.","Mirror production's lock-capable store in tests rather than 'array'.","Guard funnel()/block() calls with a LockProvider instanceof check."],"tags":["cache","locks","configuration","laravel"],"backgroundTag":null,"analyzedSha":"e0f6eb3518ac29fbbca8529e97d0df7fc9f24481","analyzedAt":"2026-08-11T20:52:37.562Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}