symfony/http-kernel · error · RuntimeException

Unable to store the entity.

Error message

Unable to store the entity.

What it means

Store::write() generates a content digest for the response body and calls save() to persist the body file; if the underlying Store::save() implementation fails to write the content, this RuntimeException is thrown because the cache entry would be incomplete.

Solutions

  1. Check the cache directory exists and is writable by the PHP process (e.g. chmod/chown var/cache)
  2. Verify free disk space and inode/quota limits
  3. Fix filesystem-level blocks (open_basedir, SELinux) or point the cache to a writable location
Defensive patterns

Strategy: try-catch

Validate before calling

$dir = ini_get('open_basedir') ? null : $cacheDir;
is_dir($cacheDir) && is_writable($cacheDir) || throw new \RuntimeException("Cache dir $cacheDir not writable");
disk_free_space($cacheDir) > 1024 * 1024 || throw new \RuntimeException('Cache disk nearly full');

Try / catch

try {
    $store->write($request, $response);
} catch (\RuntimeException $e) {
    $logger->error('HTTP cache entity write failed: '.$e->getMessage());
    return $response; // serve uncached instead of failing the request
}

Prevention

When it happens

Trigger: save() returns false during write() — usually the content file could not be written: full disk, wrong permissions on the cache directory, or a custom Store subclass whose save() fails for the digest key.

Common situations: Cache directory owned by another user or read-only in production; disk quota exceeded; NFS/network filesystem write failures; SELinux or open_basedir blocking writes to the cache path.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of symfony/http-kernel@aa3a39d728 (2026-09-13). Data as JSON: /api/errors/8bee4653c4fa298c. Report an issue: GitHub.

Appendix: source

Thrown at HttpCache/Store.php:205

            }

            $digest = $response->headers->get('X-Content-Digest');
            if ($this->getPath($digest) !== $response->headers->get('X-Body-File')) {
                throw new \RuntimeException('X-Body-File and X-Content-Digest do not match.');
            }
        // Everything seems ok, omit writing content to disk
        } else {
            // Responses that cannot provide their content, like BinaryFileResponse or
            // StreamedResponse, have no entity to store, so no entry is written
            if (false === $content = $response->getContent()) {
                return $key;
            }

            $digest = $this->generateContentDigest($response);
            $response->headers->set('X-Content-Digest', $digest);

            if (!$this->save($digest, $content, false)) {
                throw new \RuntimeException('Unable to store the entity.');
            }

            if (!$response->headers->has('Transfer-Encoding')) {
                $response->headers->set('Content-Length', \strlen($content));
            }
        }

        // read existing cache entries, remove non-varying, and add this one to the list
        $entries = [];
        $vary = implode(', ', $response->headers->all('vary'));
        foreach ($this->getMetadata($key) as $entry) {
            if (!$this->requestsMatch($vary ?? '', $entry[0], $storedEnv)) {
                $entries[] = $entry;
            }
        }

        $headers = $this->persistResponse($response);
        unset($headers['age']);

View on GitHub (pinned to aa3a39d728)