laravel/framework · warning · RuntimeException

This lock driver does not support refreshing locks.

Error message

This lock driver does not support refreshing locks.

What it means

The abstract base Lock::refresh() throws RuntimeException because not all lock backends support extending a held lock's TTL. Drivers that support it (e.g. RedisLock, PhpRedisLock) override refresh(); drivers that don't (e.g. ArrayLock, DynamoDbLock) inherit the throwing implementation.

Source

Thrown at src/Illuminate/Cache/Lock.php:149

            try {
                return $callback();
            } finally {
                $this->release();
            }
        }

        return true;
    }

    /**
     * Attempt to refresh the lock for the given number of seconds.
     *
     * @param  int|null  $seconds
     * @return bool
     */
    public function refresh($seconds = null)
    {
        throw new RuntimeException('This lock driver does not support refreshing locks.');
    }

    /**
     * Returns the current owner of the lock.
     *
     * @return string
     */
    public function owner()
    {
        return $this->owner;
    }

    /**
     * Determine if the lock is currently held by any process.
     *
     * @return bool
     */
    public function isLocked(): bool

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Use a refresh-capable driver (redis, database) if your workload relies on extending locks.
  2. Guard the call: check the concrete class before calling refresh().
  3. Instead of refresh(), release and re-acquire the lock to extend ownership on drivers without native refresh.
  4. In tests, mock the lock or use a redis-compatible fake if refresh() must succeed.

Example fix

// before
$lock = Cache::store('array')->lock('orders', 60);
$lock->block(5);
$lock->refresh(60); // throws on array driver

// after (release + re-acquire)
$lock->release();
$lock = Cache::store('array')->lock('orders', 60);
$lock->block(5);
// or switch store to redis/database for refresh support
Defensive patterns

Strategy: type-guard

Validate before calling

$lock = Cache::lock('orders', 60);
$reflectable = new \ReflectionMethod($lock, 'refresh');
if ($reflectable->getDeclaringClass()->getName() === \Illuminate\Cache\Lock::class) {
    throw new \RuntimeException('This lock driver does not support refresh(); use redis/database.');
}
$lock->refresh(60);

Type guard

function lockSupportsRefresh(\Illuminate\Contracts\Cache\Lock $lock): bool
{
    return (new \ReflectionMethod($lock, 'refresh'))
        ->getDeclaringClass()->getName() !== \Illuminate\Cache\Lock::class;
}

Try / catch

try {
    $lock->refresh(60);
} catch (\RuntimeException $e) {
    if (str_contains($e->getMessage(), 'does not support refreshing')) {
        $lock->release();
        $lock = Cache::lock('orders', 60);
        $lock->block(5);
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Acquiring a lock via Cache::lock('x') then calling $lock->refresh(30) when the underlying store is array, file, or another driver whose Lock subclass does not override refresh().

Common situations: Using the array driver in tests and exercising long-running lock code that calls refresh(). Switching a cache driver from redis to array/file and forgetting that refresh() is unsupported. Writing library code that assumes all locks are refreshable.

Related errors


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