laravel/framework · error · BadMethodCallException
This cache store does not support locks.
Error message
This cache store does not support locks.
What it means
Thrown by Cache\Repository::funnel() when the configured cache store does not implement Illuminate\Contracts\Cache\LockProvider. Atomic locks (Cache::lock, block, funnel, throttle) require lock support that file/array/DynamoDB stores do not provide.
Source
Thrown at src/Illuminate/Cache/Repository.php:742
* @return TReturn
*
* @throws \Illuminate\Contracts\Cache\LockTimeoutException
*/
public function withoutOverlapping($key, callable $callback, $lockFor = 0, $waitFor = 10, $owner = null)
{
return $this->store->lock(enum_value($key), $lockFor, $owner)->block($waitFor, $callback);
}
/**
* Funnel a callback for a maximum number of simultaneous executions.
*
* @param \UnitEnum|string $name
* @return \Illuminate\Cache\Limiters\ConcurrencyLimiterBuilder
*/
public function funnel($name)
{
if (! $this->store instanceof LockProvider) {
throw new BadMethodCallException('This cache store does not support locks.');
}
return new ConcurrencyLimiterBuilder($this, enum_value($name));
}
/**
* Remove an item from the cache.
*
* @param \UnitEnum|array|string $key
* @return bool
*/
public function forget($key)
{
$key = enum_value($key);
$this->event(new ForgettingKey($this->getName(), $key));
return tap($this->store->forget($this->itemKey($key)), function ($result) use ($key) {View on GitHub (pinned to bd6b5437e6)
Solutions
- Switch CACHE_STORE to redis, database, memcached, or dynamodb (all implement LockProvider).
- Guard the call: if (Cache::getStore() instanceof \Illuminate\Contracts\Cache\LockProvider) { ... }.
- In phpunit set CACHE_STORE=array only for tests that don't exercise locks, and use a dedicated redis connection for lock tests.
- Refactor away from locks (e.g., use a DB unique constraint or a job middleware) if no lock-capable store is available.
Example fix
// before
Cache::lock('process:'.$id, 60)->block(5, fn () => doWork());
// after (env)
// .env: CACHE_STORE=redis
// or guard at runtime
if (Cache::getStore() instanceof \Illuminate\Contracts\Cache\LockProvider) {
Cache::lock('process:'.$id, 60)->block(5, fn () => doWork());
} else {
doWork();
} Defensive patterns
Strategy: validation
Validate before calling
if (! (Cache::getStore() instanceof \Illuminate\Contracts\Cache\LockProvider)) {
// locks unavailable; choose a fallback path
} Type guard
function cacheSupportsLocks(): bool {
return Cache::getStore() instanceof \Illuminate\Contracts\Cache\LockProvider;
} Try / catch
try {
Cache::lock('job:'.$id, 60)->block(5, fn () => doWork());
} catch (\BadMethodCallException $e) {
// store lacks lock support; run without a lock or fail loudly
doWork();
} Prevention
- Keep CACHE_STORE consistent between environments that exercise locks (redis/database).
- Guard lock usage with an instanceof LockProvider check.
- In tests, only assert lock behavior when the backing store supports it.
When it happens
Trigger: Calling Cache::funnel('name'), Cache::lock('key'), or Cache::block('key', $cb) while CACHE_DRIVER/STORE is file, array, or another non-LockProvider store.
Common situations: Local dev with CACHE_STORE=file (or array in tests) hitting a Cache::lock()/->block() call that works in prod with redis/database; running queue/job code that uses Cache::lock in the testing environment.
Related errors
- This cache store does not support flushing locks.
- This cache store does not support tagging.
- Flushing locks is only supported when the lock store is sepa
- Flushing locks is only supported when the lock store is sepa
- Flushing locks is only supported when the lock store is sepa
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/04e9c28e7147d10f.json.
Report an issue: GitHub.