slimphp/Slim · error · RuntimeException

Route collector cache file directory `%s` is not writable

Error message

Route collector cache file directory `%s` is not writable

What it means

Slim's RouteCollector::setCacheFile() validates the route-cache location when the app boots: if the cache file does not exist yet, the parent directory must be writable so FastRoute can create it. This RuntimeException is thrown when the file is absent and is_writable(dirname($cacheFile)) fails, meaning Slim cannot persist the compiled route table. It is a fail-fast configuration check that fires during App construction or the first setCacheFile() call, before any request is served.

Source

Thrown at Slim/Routing/RouteCollector.php:146

     */
    public function getCacheFile(): ?string
    {
        return $this->cacheFile;
    }

    /**
     * {@inheritdoc}
     */
    public function setCacheFile(string $cacheFile): RouteCollectorInterface
    {
        if (file_exists($cacheFile) && !is_readable($cacheFile)) {
            throw new RuntimeException(
                sprintf('Route collector cache file `%s` is not readable', $cacheFile)
            );
        }

        if (!file_exists($cacheFile) && !is_writable(dirname($cacheFile))) {
            throw new RuntimeException(
                sprintf('Route collector cache file directory `%s` is not writable', dirname($cacheFile))
            );
        }

        $this->cacheFile = $cacheFile;
        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getBasePath(): string
    {
        return $this->basePath;
    }

    /**
     * Set the base path used in urlFor()

View on GitHub (pinned to 80900fb39c)

Solutions

  1. Use an absolute path built from the app root, e.g. __DIR__ . '/var/cache/routes.php', instead of a relative one
  2. Create the directory before enabling the cache: if (!is_dir($dir)) { mkdir($dir, 0775, true); }
  3. Grant write permission to the PHP process user: chown -R www-data var/cache or chmod 775, then verify with sudo -u www-data test -w var/cache
  4. If the directory is on a read-only mount (container), move the cache to a writable volume or disable route caching in that environment

Example fix

// before
$app = AppFactory::create();
$app->getRouteCollector()->setCacheFile('cache/routes.php'); // relative path, dir may not exist or not be writable

// after
$cacheDir = __DIR__ . '/var/cache';
if (!is_dir($cacheDir)) {
    mkdir($cacheDir, 0775, true);
}
$app = AppFactory::create();
$app->getRouteCollector()->setCacheFile($cacheDir . '/routes.php');
Defensive patterns

Strategy: validation

Validate before calling

$cacheFile = __DIR__ . '/var/cache/routes.php';
$cacheDir = dirname($cacheFile);
if (!is_dir($cacheDir)) {
    mkdir($cacheDir, 0775, true);
}
if (!is_writable($cacheDir)) {
    throw new RuntimeException(
        sprintf('Route cache dir %s not writable for user %s — fix before enabling cache', $cacheDir, get_current_user())
    );
}
$app->getRouteCollector()->setCacheFile($cacheFile);

Try / catch

try {
    $app->getRouteCollector()->setCacheFile($cacheFile);
} catch (RuntimeException $e) {
    // boot-time config failure: surface a clear ops message instead of a 500 on first request
    $log->error($e->getMessage());
    // optionally continue without cache in non-production: omit setCacheFile()
    throw $e;
}

Prevention

When it happens

Trigger: Calling $app->getRouteCollector()->setCacheFile($file) (or passing a 'routeCacheFile' setting / RouteCollector constructor argument) where $file does not exist and its directory is not writable for the PHP process user. Typical with a relative path like 'cache/routes.php' when the web-server cwd is public/, a never-created cache/ directory, or a directory owned by the deploy user while php-fpm/apache runs as www-data.

Common situations: Deployment where the cache directory was not created (mkdir missing from provisioning); Docker images with read-only volumes or multi-stage builds that drop the cache dir; CLI warm-up scripts run as root creating root-owned files/dirs that the web user cannot write to; SELinux or safe-mode restrictions blocking writes; relative paths that resolve differently between CLI and web contexts.

Related errors


AI-assisted analysis of slimphp/Slim@80900fb39c (2026-08-21). Data as JSON: /api/errors/5f98ac05825f9561. Report an issue: GitHub.