doctrine/orm · error · LogicException

If you want to use a "READ_WRITE" cache an implementation of

Error message

If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you want to use it please provide a valid directory, DefaultCacheFactory#setFileLockRegionDirectory(). 

What it means

LogicException from DefaultCacheFactory::getRegion() (src/Cache/DefaultCacheFactory.php:160). Something is cached with usage READ_WRITE, and the default factory implements READ_WRITE locking via FileLockRegion — but no lock directory was configured, so it cannot build the required ConcurrentRegion and refuses to fall back to an unlocked region (which would silently break consistency).

Source

Thrown at src/Cache/DefaultCacheFactory.php:160

    /**
     * {@inheritDoc}
     */
    public function getRegion(array $cache): Region
    {
        if (isset($this->regions[$cache['region']])) {
            return $this->regions[$cache['region']];
        }

        $name     = $cache['region'];
        $lifetime = $this->regionsConfig->getLifetime($cache['region']);
        $region   = new DefaultRegion($name, $this->cacheItemPool, $lifetime);

        if ($cache['usage'] === ClassMetadata::CACHE_USAGE_READ_WRITE) {
            if (
                $this->fileLockRegionDirectory === '' ||
                $this->fileLockRegionDirectory === null
            ) {
                throw new LogicException(
                    'If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, ' .
                    'The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you want to use it please provide a valid directory, DefaultCacheFactory#setFileLockRegionDirectory(). ',
                );
            }

            $directory = $this->fileLockRegionDirectory . DIRECTORY_SEPARATOR . $cache['region'];
            $region    = new FileLockRegion($region, $directory, (string) $this->regionsConfig->getLockLifetime($cache['region']));
        }

        return $this->regions[$cache['region']] = $region;
    }

    public function getTimestampRegion(): TimestampRegion
    {
        if ($this->timestampRegion === null) {
            $name     = Cache::DEFAULT_TIMESTAMP_REGION_NAME;
            $lifetime = $this->regionsConfig->getLifetime($name);

View on GitHub (pinned to d9b9ff7301)

Solutions

  1. Call $cacheFactory->setFileLockRegionDirectory('/var/cache/app/doctrine-lock') (a writable, preferably local, path) before the entity manager is used — regions are built lazily and memoized, so configure it in the factory bootstrap.
  2. In Symfony with doctrine-bundle, set the second-level-cache file lock region directory option (doctrine.orm.second_level_cache.file_lock_region_directory) instead of hand-calling the factory.
  3. If strict locking is unnecessary, change usage to NONSTRICT_READ_WRITE, which needs no lock directory.
  4. Keep the directory out of the project root and exclude it from deployments/rsync so lock files do not leak between releases.

Example fix

// before
$factory = new DefaultCacheFactory($regionsConfig, $cacheItemPool);
$ormConfig->setSecondLevelCacheEnabled(true);
// entity has #[Cache(usage: 'READ_WRITE')] -> LogicException at runtime

// after
$factory = new DefaultCacheFactory($regionsConfig, $cacheItemPool);
$factory->setFileLockRegionDirectory(sys_get_temp_dir() . '/doctrine-slc-lock');
$ormConfig->setSecondLevelCacheEnabled(true);
$ormConfig->getSecondLevelCacheConfiguration()->setCacheFactory($factory);
Defensive patterns

Strategy: validation

Validate before calling

$factory = new DefaultCacheFactory($regionsConfig, $pool);
if ($anyReadWriteUsage) {
    $dir = sys_get_temp_dir() . '/doctrine-slc-lock';
    if (! is_dir($dir)) { mkdir($dir, 0775, true); }
    $factory->setFileLockRegionDirectory($dir);
}

Prevention

When it happens

Trigger: Any entity or association mapped with `#[Cache(usage: 'READ_WRITE')]` (second-level cache enabled) while DefaultCacheFactory::setFileLockRegionDirectory() was never called or was called with '' — the factory's $fileLockRegionDirectory is null/empty when the region is first requested.

Common situations: Enabling the second-level cache in a new project and copying `usage: READ_WRITE` from docs without configuring the lock directory; Symfony doctrine-bundle setups missing the file_lock_region_directory setting; turning on SLI cache after an upgrade where the directory config lived in removed bootstrap code.

Related errors


AI-assisted analysis of doctrine/orm@d9b9ff7301 (2026-08-21). Data as JSON: /api/errors/a03f87d4fb17b3d9. Report an issue: GitHub.