Open chrif opened 7 months ago
Can you share the stack trace of the exception you got to see when it was triggered in each case ?
Below you will find my initial reply, but I found the trigger in production while trying to get the full stack trace. It is the opcache preload.php
file that triggers the error. If I comment opcache.preload=/app/config/preload.php
in php.ini, I don't get the error, and if I keep it but set APP_DEBUG=1
, I don't get the error either.
Versions
doctrine/doctrine-bundle 2.11.3
doctrine/orm 2.19.0
symfony/framework-bundle v6.4.4
Stack trace for the prod cache clear functional test when it fails with enable_lazy_ghost_objects: false
In InvalidArgumentException.php line 102:
[Doctrine\Common\Proxy\Exception\InvalidArgumentException]
Unable to create a proxy for a readonly class "App\Entity\MyEntity".
Exception trace:
at /app/vendor/doctrine/common/src/Proxy/Exception/InvalidArgumentException.php:102
Doctrine\Common\Proxy\Exception\InvalidArgumentException::classMustNotBeReadOnly() at /app/vendor/doctrine/common/src/Proxy/ProxyGenerator.php:372
Doctrine\Common\Proxy\ProxyGenerator->verifyClassCanBeProxied() at /app/vendor/doctrine/common/src/Proxy/ProxyGenerator.php:312
Doctrine\Common\Proxy\ProxyGenerator->generateProxyClass() at /app/vendor/doctrine/common/src/Proxy/AbstractProxyFactory.php:146
Doctrine\Common\Proxy\AbstractProxyFactory->generateProxyClasses() at /app/vendor/doctrine/orm/src/Proxy/ProxyFactory.php:228
Doctrine\ORM\Proxy\ProxyFactory->generateProxyClasses() at /app/vendor/symfony/doctrine-bridge/CacheWarmer/ProxyCacheWarmer.php:60
Symfony\Bridge\Doctrine\CacheWarmer\ProxyCacheWarmer->warmUp() at /app/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php:108
Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate->warmUp() at /app/vendor/symfony/http-kernel/Kernel.php:545
Symfony\Component\HttpKernel\Kernel->initializeContainer() at /app/vendor/symfony/http-kernel/Kernel.php:763
Symfony\Component\HttpKernel\Kernel->preBoot() at /app/vendor/symfony/http-kernel/Kernel.php:126
Symfony\Component\HttpKernel\Kernel->boot() at /app/library/Common/Application/Kernel.php:34
App\Kernel->boot() at /app/vendor/symfony/http-kernel/Kernel.php:144
Symfony\Component\HttpKernel\Kernel->reboot() at /app/vendor/symfony/framework-bundle/Command/CacheClearCommand.php:229
Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand->warmup() at /app/vendor/symfony/framework-bundle/Command/CacheClearCommand.php:141
Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand->execute() at /app/vendor/symfony/console/Command/Command.php:326
Symfony\Component\Console\Command\Command->run() at /app/vendor/symfony/console/Application.php:1096
Symfony\Component\Console\Application->doRunCommand() at /app/vendor/symfony/framework-bundle/Console/Application.php:126
Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /app/vendor/symfony/console/Application.php:324
Symfony\Component\Console\Application->doRun() at /app/vendor/symfony/framework-bundle/Console/Application.php:80
Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /app/vendor/symfony/console/Application.php:175
Symfony\Component\Console\Application->run() at /app/vendor/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php:49
Symfony\Component\Runtime\Runner\Symfony\ConsoleApplicationRunner->run() at /app/vendor/autoload_runtime.php:39
require_once() at /app/application/console:8
cache:clear [--no-warmup] [--no-optional-warmers] [--maintenance-override MAINTENANCE-OVERRIDE]
In production when it fails with enable_lazy_ghost_objects: true
I don't have the full stack trace. If I use APP_DEBUG=true, I don't get the error. If it's not enough, I'll have to figure this out.
<b>Fatal error</b>: Non-readonly class Proxies\__CG__\App\Entity\MyEntity cannot extend readonly class App\Entity\MyEntity in <b>/app/var/cache/production/doctrine/orm/Proxies/__CG__AppEntityMyEntity.php</b> on line <b>8</b><br />
Indeed, the new implementation of ProxyFactory does not seem to validate the compatibility of classes at proxy generation time, but only when the proxy class is used.
/cc @nicolas-grekas
I guess this is an issue in var-dumper? Shall we close here?
I think this is for the ORM. VarExporter's lazy objects are compatible with readonly classes. But I'm not sure the ORM takes care of them properly (either failing early or generaton readonly proxies.)
Can you create a reproducer for this issue?
Can you create a reproducer for this issue?
I'll make time next week for that.
The error "the Unable to create a proxy for a readonly class" is only triggered when lazy ghost objects is false during ProxyFactory::generateProxyClasses
. There is no other way this exception inside the ProxyGenerator can be triggered, because its from the old code.
Some hints, A reproducer for the fatal error with lazy proxy should be a test with a readonly class, see @requires PHP 8.1
and other uses in the testsuite to restrict run for php with readonly classes. Call $this->_em->getReference()
to create a proxy.
enable_lazy_ghost_objects: false
is deprecated, but when it istrue
, clearing the Symfony cache is not enough to get theUnable to create a proxy for a readonly class
error. It is only when the proxy class is used that we get it.So in dev we have
auto_generate_proxy_classes: true
and we didn't get an error when developing. I guess the problematic proxy was not used in the development use case.In production we have
auto_generate_proxy_classes: false
as recommended. We also have a functional test to check that the prod Symfony cache can be cleared. It passed the test.It's only when we released and used the proxy class that we got the
Unable to create a proxy for a readonly class
.With
enable_lazy_ghost_objects: false
everything works fine, but we have a deprecation message.