symfony/http-kernel · error · LogicException
" ::warmUp()" should return a list of files or classes but…
Error message
"%s::warmUp()" should return a list of files or classes but "%s" is none of them.
What it means
CacheWarmerAggregate::warmUp() iterates each warmer's warmUp() return values and requires them to be existing files/directories under the cache dir or class names for preload. A LogicException is thrown when a warmer returns an item that is neither (e.g. a non-existent path or invalid string), catching warmer implementations that violate the contract.
Solutions
- Fix the warmer so warmUp() returns only existing absolute file paths under the cache/build dir or valid class names.
- If the warmer writes no files, return [] (or only class names to preload).
- Verify paths exist after writing them in the warmer (file_exists assertion) before returning them.
Example fix
// before
class MyWarmer implements CacheWarmerInterface
{
public function warmUp(string $cacheDir, ?string $buildDir = null): array
{
return ['var/cache/prod/missing.xml']; // never written
}
}
// after
class MyWarmer implements CacheWarmerInterface
{
public function warmUp(string $cacheDir, ?string $buildDir = null): array
{
$file = $cacheDir.'/my/data.php';
file_put_contents($file, '<?php return [];');
return [$file];
}
} Defensive patterns
Strategy: validation
Validate before calling
$items = $warmer->warmUp($cacheDir, $buildDir);
foreach ($items as $item) {
$valid = is_dir($item) || is_file($item) || (class_exists($item) && interface_exists($item) === false);
if (!$valid) { throw new \AssertionError("Invalid warmer return: $item"); }
} Try / catch
try { $aggregate->warmUp($cacheDir); } catch (\LogicException $e) { /* fix the offending warmer named in the message */ } Prevention
- Unit-test custom warmers to assert return values exist on disk or are class names
- Return [] when a warmer produces no preloadable artifacts
- Keep warmer paths absolute and inside the cache/build dir
When it happens
Trigger: A custom CacheWarmerInterface::warmUp() returns an array containing a path that is not an existing file under dirname($cacheDir)/dirname($buildDir), or a malformed entry that is neither a valid path nor a class name.
Common situations: Custom warmers returning generated file paths that were never written, returning relative paths outside the cache dir, or (after Symfony 6.3 contract change) returning wrong/empty string items; upgrading Symfony where warmer return values became meaningful for preload.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Request payload contains invalid "form" data.
- Unsupported format: " ".
- Request payload contains invalid
- Request payload contains invalid
- The uid for the " " parameter is invalid.
AI-assisted analysis of symfony/http-kernel@aa3a39d728 (2026-09-13).
Data as JSON: /api/errors/21ab8a53e1102238.
Report an issue: GitHub.
Appendix: source
Thrown at CacheWarmer/CacheWarmerAggregate.php:98
return null;
});
}
$preload = [];
try {
foreach ($this->warmers as $warmer) {
if (!$this->optionalsEnabled && $warmer->isOptional()) {
continue;
}
if ($this->onlyOptionalsEnabled && !$warmer->isOptional()) {
continue;
}
$start = microtime(true);
foreach ($warmer->warmUp($cacheDir, $buildDir) as $item) {
if (is_dir($item) || (str_starts_with($item, \dirname($cacheDir)) && !is_file($item)) || ($buildDir && str_starts_with($item, \dirname($buildDir)) && !is_file($item))) {
throw new \LogicException(\sprintf('"%s::warmUp()" should return a list of files or classes but "%s" is none of them.', $warmer::class, $item));
}
$preload[] = $item;
}
if ($io?->isDebug()) {
$io->info(\sprintf('"%s" completed in %0.2fms.', $warmer::class, 1000 * (microtime(true) - $start)));
}
}
} finally {
if ($collectDeprecations) {
restore_error_handler();
if ($h = fopen($this->deprecationLogsFilepath, 'c+')) {
flock($h, \LOCK_EX);
set_error_handler(static fn () => true);
try {
$previousLogs = unserialize(stream_get_contents($h), ['allowed_classes' => false]);View on GitHub (pinned to aa3a39d728)