laravel/framework · warning · RuntimeException

Flushing locks is only supported when the lock store is sepa

Error message

Flushing locks is only supported when the lock store is separate from the cache store.

What it means

RedisStore::flushLocks() throws if hasSeparateLockStore() is false, i.e. when the lock connection name equals the cache connection name ($this->lockConnection === $this->connection). Flushing only locks via FLUSHDB is only safe when locks live on a dedicated Redis connection/database.

Source

Thrown at src/Illuminate/Cache/RedisStore.php:313

     */
    public function flush()
    {
        $this->connection()->flushdb();

        return true;
    }

    /**
     * Remove all locks from the store.
     *
     * @return bool
     *
     * @throws \RuntimeException
     */
    public function flushLocks(): bool
    {
        if (! $this->hasSeparateLockStore()) {
            throw new RuntimeException('Flushing locks is only supported when the lock store is separate from the cache store.');
        }

        $this->lockConnection()->flushdb();

        return true;
    }

    /**
     * Remove all expired tag set entries.
     *
     * @return void
     */
    public function flushStaleTags()
    {
        foreach ($this->currentTags()->chunk(1000) as $tags) {
            $this->tags($tags->all())->flushStale();
        }
    }

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Add a distinct 'lock_connection' (e.g. 'cache-locks') in the redis store config pointing to a different Redis connection/database.
  2. Define that connection in config/database.php 'redis' block (e.g. database => 1).
  3. If a single connection is intentional, call flush() to clear everything rather than flushLocks().

Example fix

// before
'redis' => [
    'driver' => 'redis',
    'connection' => 'cache',
    // no lock_connection -> equals 'cache' -> throws
],

// after
'redis' => [
    'driver' => 'redis',
    'connection' => 'cache',
    'lock_connection' => 'cache-locks',
],
// config/database.php redis block:
'cache-locks' => [
    'host' => env('REDIS_HOST'),
    'database' => 1,
],
Defensive patterns

Strategy: validation

Validate before calling

$store = Cache::store('redis')->getStore();
if ($store instanceof \Illuminate\Cache\RedisStore && ! $store->hasSeparateLockStore()) {
    throw new \RuntimeException('Redis cache requires a distinct lock_connection to flushLocks().');
}
$store->flushLocks();

Type guard

function redisCacheHasSeparateLocks(\Illuminate\Contracts\Cache\Store $store): bool
{
    return $store instanceof \Illuminate\Cache\RedisStore
        && $store->hasSeparateLockStore();
}

Try / catch

try {
    Cache::store('redis')->getStore()->flushLocks();
} catch (\RuntimeException $e) {
    if (str_contains($e->getMessage(), 'lock store is separate')) {
        Cache::store('redis')->flush();
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Configuring a redis cache store without 'lock_connection' (so it defaults to the same connection), then calling Cache::store('redis')->getStore()->flushLocks() or Artisan cache:clear-locks. The guard fires whenever lock_connection is unset or equal to connection.

Common situations: Default redis store config omits lock_connection. Using the same Redis DB (e.g. db 0) for both cache values and locks. Sharing a redis connection alias for simplicity and then attempting selective lock flushing.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/9ad59716178314c0.json. Report an issue: GitHub.