rectorphp/rector · error · CachingException
Could not write data to cache file %s.
Error message
Could not write data to cache file %s.
What it means
FileCacheStorage::save() writes each item to a temp file then @copy()s it into the two-level cache directory. If the copy fails and the platform is not Windows-with-existing-target, it throws CachingException naming the unreachable cache file. This is a filesystem-level failure: permissions, missing directory, or a full disk, almost never a Rector bug.
Source
Thrown at src/Caching/ValueObject/Storage/FileCacheStorage.php:77
$this->filesystem->mkdir($cacheFilePaths->getFirstDirectory());
$this->filesystem->mkdir($cacheFilePaths->getSecondDirectory());
$filePath = $cacheFilePaths->getFilePath();
$tmpPath = \sprintf('%s/%s.tmp', $this->directory, Random::generate());
$errorBefore = \error_get_last();
$exported = @\var_export(new CacheItem($variableKey, $data), \true);
$errorAfter = \error_get_last();
if ($errorAfter !== null && $errorBefore !== $errorAfter) {
throw new CachingException(\sprintf('Error occurred while saving item %s (%s) to cache: %s', $key, $variableKey, $errorAfter['message']));
}
// for performance reasons we don't use SmartFileSystem
FileSystem::write($tmpPath, \sprintf("<?php declare(strict_types = 1);\n\nreturn %s;", $exported), null);
$copySuccess = @\copy($tmpPath, $filePath);
@\unlink($tmpPath);
if ($copySuccess) {
return;
}
if (\DIRECTORY_SEPARATOR === '/' || !\file_exists($filePath)) {
throw new CachingException(\sprintf('Could not write data to cache file %s.', $filePath));
}
}
public function clean(string $key): void
{
$cacheFilePaths = $this->getCacheFilePaths($key);
$this->processRemoveCacheFilePath($cacheFilePaths);
$this->processRemoveEmptyDirectory($cacheFilePaths->getSecondDirectory());
$this->processRemoveEmptyDirectory($cacheFilePaths->getFirstDirectory());
}
public function clear(): void
{
FileSystem::delete($this->directory);
}
private function processRemoveCacheFilePath(CacheFilePaths $cacheFilePaths): void
{
$filePath = $cacheFilePaths->getFilePath();
if (!$this->filesystem->exists($filePath)) {
return;View on GitHub (pinned to 408fcb0ff1)
Solutions
- Fix ownership/permissions of the cache directory: rm -rf .cache/rector (or /tmp/rector) so the current user recreates it
- Point the cache to a writable, per-user location: ->withCacheDirectory(__DIR__ . '/.rector-cache') or the cacheDirectory option
- Check disk space and quota: df -h on the filesystem holding the cache dir
- In CI, avoid concurrent rector runs sharing one cache directory (matrix jobs without distinct caches)
Example fix
# before: cache dir owned by root, run as ci user vendor/bin/rector process src # CachingException: Could not write data to cache file # after: give the run its own writable cache rm -rf .cache/rector vendor/bin/rector process src --cache-directory .rector-cache-ci
Defensive patterns
Strategy: fallback
Validate before calling
// preflight in CI: verify the cache directory is writable by this user
$cacheDir = sys_get_temp_dir() . '/rector'; // or your configured cacheDirectory
if (is_dir($cacheDir) && ! is_writable($cacheDir)) {
fwrite(STDERR, "Cache dir not writable: {$cacheDir}\n");
exit(1);
} Try / catch
catch \Rector\Caching\Exception\CachingException, inspect the path in the message, fix permissions/chown, then retry the run; do not ignore -- a failed cache write silently costs full re-analysis on every run.
Prevention
- Run rector under a single consistent user in CI/Docker (avoid root-then-non-root on the same cache dir)
- Give each CI job/matrix leg its own cache directory
- Monitor free disk space on the filesystem hosting the cache directory
When it happens
Trigger: The cache directory (default under sys temp or the configured cacheDirectory) is not writable by the current user: cache created by root then reused by a CI user, a read-only mount, disk quota exhausted, or a parallel job racing to delete directories (clean/clear-cache) while others save.
Common situations: Docker/CI where one stage runs rector as root and another as non-root; deploy pipelines running rector on read-only artifacts; /tmp cleanup daemons removing the temp file between write and copy.
Related errors
- Provide only PHP file, ready for Dependency Injection. "%s"
- Error occurred while saving item %s (%s) to cache: %s
- File %s is not readable
- "%s" rule is deprecated, as turning a docblock type into a r
- "%s" rule is deprecated, as risky. The "??" and "?:" operato
AI-assisted analysis of rectorphp/rector@408fcb0ff1 (2026-08-21).
Data as JSON: /api/errors/08ee92ebca0e3b7a.
Report an issue: GitHub.