symfony/symfony · error · DomainException
Class not found:
Error message
Class not found:
What it means
DefaultMarshaller::handleUnserializeCallback() is registered as unserialize_callback_func inside unmarshall(). When unserialize() encounters a class it cannot autoload, PHP calls this callback with the missing class name, which throws a DomainException. This surfaces missing-class cache corruption loudly instead of letting unserialize silently instantiate __PHP_Incomplete_Class.
Source
Thrown at src/Symfony/Component/Cache/Marshaller/DefaultMarshaller.php:94
throw new \RuntimeException('Failed to unserialize values, did you forget to install the "igbinary" extension?');
} elseif (null !== $value = igbinary_unserialize($value)) {
return $value;
}
throw new \DomainException(error_get_last() ? error_get_last()['message'] : 'Failed to unserialize values.');
} catch (\Error $e) {
throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine());
} finally {
ini_set('unserialize_callback_func', $unserializeCallbackHandler);
}
}
/**
* @internal
*/
public static function handleUnserializeCallback(string $class): never
{
throw new \DomainException('Class not found: '.$class);
}
}
View on GitHub (pinned to 698e28026c)
Solutions
- Clear the cache pool to evict blobs referencing the old/missing class.
- Restore the class (re-enable its bundle, run composer dump-autoload, fix the namespace).
- Invalidate by bumping the cache namespace after any rename of cached value classes.
- Keep cached value classes in stable, always-loaded namespaces.
Example fix
// before — blob references App\Legacy\UserDTO which was moved to App\UserDTO $marshaller->unmarshall($blob); // DomainException: Class not found: App\Legacy\UserDTO // after — flush stale blobs and/or keep the class autoloadable $pool->clear(); // or bump namespace to invalidate all old entries $pool = new RedisAdapter($redis, 'app_v2_');
Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure cached value classes are autoloadable before reading
foreach (self::CACHED_VALUE_CLASSES as $fqcn) {
if (!class_exists($fqcn)) {
throw new \LogicException("Cached value class $fqcn is not autoloadable; flush cache or restore the class.");
}
} Try / catch
try {
return $marshaller->unmarshall($blob);
} catch (\DomainException $e) {
if (str_starts_with($e->getMessage(), 'Class not found:')) {
$pool->deleteItem($key);
return $loader();
}
throw $e;
} Prevention
- Keep cached value classes in stable, always-loaded namespaces.
- Bump the cache namespace when renaming/removing a cached value class.
- Run composer dump-autoload and align enabled bundles across all processes.
- Flush shared caches after refactors that touch cached entities.
When it happens
Trigger: unmarshall() decodes a blob referencing a class that is not autoloadable at read time — e.g. the value's class was renamed/removed/disabled between write and read. Distinct from the adapter-level callback (error 565): this fires within the marshaller's unmarshall() path.
Common situations: Renaming or deleting a cached value class without clearing the cache; running a worker with fewer bundles/extensions enabled than the writer; partial deploy where classmap is out of sync; composer autoload mismatch after a refactor.
Related errors
- Class not found:
- The "marshaller" attribute of the "cache.pool" tag for servi
- The "marshaller" attribute of the "cache.pool" tag for servi
- Please upgrade the "igbinary" PHP extension to v3.1.6 or hig
- The "igbinary" PHP extension is not loaded.
AI-assisted analysis of symfony/symfony@698e28026c (2026-08-06).
Data as JSON: /api/errors/a6262f8fe3925098.
Report an issue: GitHub.