(File)Cache trouble: yii\base\ErrorException: unserialize(): Error at offset 32765 of 32768 bytes in /var/www/.../app/vendor/yiisoft/yii2/caching/Cache.php:108

I randomly see unserialize errors in my logs like:

yii\base\ErrorException: unserialize(): Error at offset 32765 of 32768 bytes in .../vendor/yiisoft/yii2/caching/Cache.php:108
Stack trace:
#0 [internal function]: yii\base\ErrorHandler->handleError(8, 'unserialize(): ...', '/var/www/funspi...', 108, Array)
#1 .../vendor/yiisoft/yii2/caching/Cache.php(108): unserialize('a:2:{i:0;a:2:{i...')
#2 .../vendor/yiisoft/yii2/web/UrlManager.php(151): yii\caching\Cache->get('963454f612a8b5f...')
#3 .../common/localeurls/UrlManager.php(125): yii\web\UrlManager->init()
#4 .../vendor/yiisoft/yii2/base/BaseObject.php(107): common\localeurls\UrlManager->init()
#5 [internal function]: yii\base\BaseObject->__construct(Array)
#6 .../vendor/yiisoft/yii2/di/Container.php(372): ReflectionClass->newInstanceArgs(Array)
#7 .../vendor/yiisoft/yii2/di/Container.php(151): yii\di\Container->build('common\\localeur...', Array, Array)
#8 .../vendor/yiisoft/yii2/BaseYii.php(344): yii\di\Container->get('common\\localeur...', Array, Array)
#9 .../vendor/yiisoft/yii2/di/ServiceLocator.php(133): yii\BaseYii::createObject(Array)
#10 .../vendor/yiisoft/yii2/base/Application.php(563): yii\di\ServiceLocator->get('urlManager')
#11 .../vendor/yiisoft/yii2/web/Request.php(180): yii\base\Application->getUrlManager()
#12 .../vendor/yiisoft/yii2/web/Application.php(75): yii\web\Request->resolve()
#13 .../vendor/yiisoft/yii2/base/Application.php(375): yii\web\Application->handleRequest(Object(yii\web\Request))
#14 .../frontend/web/index.php(33): yii\base\Application->run()
#15 {main}

They are not reproducible. When I pull the file from the server and unserialize it manually, it works fine. I suspect it is a concurrency problem. It tends to happen more often when the server is busy.

Only solution I can think of is to suppress errors on the unserialize function in the Cache class. So, in case of an error, it will return false and it will run as if there was no cache hit.

Who has any thoughts about this fix? I have searched the web on this issue, but haven’t found any real solution so far.

How about using something like Redis for the cache instead of files?

That’s a good suggestion, thanks.

I digged in some more and found out that the cache key used by UrlManager only depends on the classname.

I recently built in an exception in my url rules that makes them different per hostname.
The Cache component then keeps invalidating the cache, forcing it to rewrite the file over and over again. When refreshing the directory I noticed the cache file size kept alternating between 2 values. Besides the performance hit, this also could explain a concurrency problem I guess.

I rewrote my UrlManager’s init() method to also include $_SERVER[“HOSTNAME”] in the key name, so a cache file per hostname is created. Hope that helps to solve the problem.

Maybe too early to draw a conclusion. Let’s see what happens over the next 24h. Serverload dropped immediately though.