Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot modify readonly property Doctrine\ORM\EntityManager::$conn #54228

Open
mathieudz opened this issue Mar 10, 2024 · 21 comments
Open

Cannot modify readonly property Doctrine\ORM\EntityManager::$conn #54228

mathieudz opened this issue Mar 10, 2024 · 21 comments

Comments

@mathieudz
Copy link

mathieudz commented Mar 10, 2024

Symfony version(s) affected

7.0.5

Description

Running Symfony 7.0 on frankenphp, I have upgraded to Doctrine ORM 3 and DBAL 4, and I intermittently get Cannot modify readonly property Doctrine\ORM\EntityManager::$conn" , which at first sight is pretty strange, because the constructor fails setting the initial value of $conn. Most probably, due to LazyGhostTrait.

Example in an HTTP request:

Uncaught PHP Exception Error: "Cannot modify readonly property Doctrine\ORM\EntityManager::$conn" at EntityManager.php line 114 {"exception":"[object] (Error(code: 0): Cannot modify readonly property Doctrine\\ORM\\EntityManager::$conn at /app/site/vendor/doctrine/orm/src/EntityManager.php:114)
[stacktrace]
#0 /app/site/var/cache/prod/ContainerCBsis9p/App_KernelProdContainer.php(391): Doctrine\\ORM\\EntityManager->__construct()
#1 /app/site/var/cache/prod/ContainerCBsis9p/App_KernelProdContainer.php(349): ContainerCBsis9p\\App_KernelProdContainer::getDoctrine_Orm_DefaultEntityManagerService()
#2 /app/site/vendor/symfony/var-exporter/Internal/LazyObjectState.php(61): ContainerCBsis9p\\App_KernelProdContainer::ContainerCBsis9p\\{closure}()
#3 /app/site/vendor/symfony/var-exporter/LazyGhostTrait.php(118): Symfony\\Component\\VarExporter\\Internal\\LazyObjectState->initialize()
#4 /app/site/vendor/doctrine/orm/src/EntityManager.php(580): ContainerCBsis9p\\EntityManagerGhost6410e2e->__get()
#5 /app/site/vendor/doctrine/orm/src/Query.php(661): Doctrine\\ORM\\EntityManager->hasFilters()
#6 /app/site/vendor/doctrine/orm/src/Query.php(221): Doctrine\\ORM\\Query->getQueryCacheId()
#7 /app/site/vendor/doctrine/orm/src/Query.php(245): Doctrine\\ORM\\Query->parse()
#8 /app/site/vendor/doctrine/orm/src/AbstractQuery.php(935): Doctrine\\ORM\\Query->_doExecute()
#9 /app/site/vendor/doctrine/orm/src/AbstractQuery.php(891): Doctrine\\ORM\\AbstractQuery->executeIgnoreQueryCache()
#10 /app/site/vendor/doctrine/orm/src/AbstractQuery.php(738): Doctrine\\ORM\\AbstractQuery->execute()
#11 /app/site/src/Repository/Doctrine/PerformanceDoctrineRepository.php(67): Doctrine\\ORM\\AbstractQuery->getOneOrNullResult()
#12 /app/site/src/Service/PerformanceService.php(49): App\\Repository\\Doctrine\\PerformanceDoctrineRepository->findById()
#13 /app/site/src/Controller/PerformancePageController.php(47): App\\Service\\PerformanceService->findById()
#14 /app/site/vendor/symfony/http-kernel/HttpKernel.php(178): App\\Controller\\PerformancePageController->__invoke()
#15 /app/site/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\\Component\\HttpKernel\\HttpKernel->handleRaw()
#16 /app/site/vendor/symfony/http-kernel/Kernel.php(185): Symfony\\Component\\HttpKernel\\HttpKernel->handle()
#17 /app/site/vendor/runtime/frankenphp-symfony/src/Runner.php(38): Symfony\\Component\\HttpKernel\\Kernel->handle()
#18 [internal function]: Runtime\\FrankenPhpSymfony\\Runner->Runtime\\FrankenPhpSymfony\\{closure}()
#19 /app/site/vendor/runtime/frankenphp-symfony/src/Runner.php(45): frankenphp_handle_request()
#20 /app/site/vendor/autoload_runtime.php(29): Runtime\\FrankenPhpSymfony\\Runner->run()
#21 /app/site/public/index.php(5): require_once('...')
#22 {main}

Example in a MessageHandler:

Fatal Error: Uncaught Error: Cannot modify readonly property Doctrine\ORM\EntityManager::$conn in /app/site/vendor/doctrine/orm/src/EntityManager.php:114
Stack trace:
#0 /app/site/var/cache/prod/ContainerCBsis9p/App_KernelProdContainer.php(391): Doctrine\ORM\EntityManager->__construct()
#1 /app/site/var/cache/prod/ContainerCBsis9p/App_KernelProdContainer.php(349): ContainerCBsis9p\App_KernelProdContainer::getDoctrine_Orm_DefaultEntityManagerService()
#2 /app/site/vendor/symfony/var-exporter/Internal/LazyObjectState.php(61): ContainerCBsis9p\App_KernelProdContainer::ContainerCBsis9p\{closure}()
#3 /app/site/vendor/symfony/var-exporter/LazyGhostTrait.php(118): Symfony\Component\VarExporter\Internal\LazyObjectState->initialize()
#4 /app/site/vendor/doctrine/orm/src/EntityManager.php(529): ContainerCBsis9p\EntityManagerGhost6410e2e->__get()
#5 /app/site/vendor/doctrine/doctrine-bundle/Registry.php(80): Doctrine\ORM\EntityManager->isOpen()
#6 /app/site/vendor/doctrine/doctrine-bundle/Registry.php(66): Doctrine\Bundle\DoctrineBundle\Registry->resetOrClearManager()
#7 /app/site/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php(57): Doctrine\Bundle\DoctrineBundle\Registry->reset()
#8 /app/site/vendor/symfony/http-kernel/Kernel.php(111): Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter->reset()
#9 /app/site/src/Kernel.php(32): Symfony\Component\HttpKernel\Kernel->boot()
#10 /app/site/vendor/symfony/http-kernel/Kernel.php(180): App\Kernel->boot()
#11 /app/site/vendor/runtime/frankenphp-symfony/src/Runner.php(38): Symfony\Component\HttpKernel\Kernel->handle()
#12 [internal function]: Runtime\FrankenPhpSymfony\Runner->Runtime\FrankenPhpSymfony\{closure}()
#13 /app/site/vendor/runtime/frankenphp-symfony/src/Runner.php(45): frankenphp_handle_request()
#14 /app/site/vendor/autoload_runtime.php(29): Runtime\FrankenPhpSymfony\Runner->run()
#15 /app/site/public/index.php(5): require_once('...')
#16 {main}
  thrown {"exception":"[object] (Symfony\\Component\\ErrorHandler\\Error\\FatalError(code: 0): Error: Uncaught Error: Cannot modify readonly property Doctrine\\ORM\\EntityManager::$conn in /app/site/vendor/doctrine/orm/src/EntityManager.php:114
Stack trace:
#0 /app/site/var/cache/prod/ContainerCBsis9p/App_KernelProdContainer.php(391): Doctrine\\ORM\\EntityManager->__construct()
#1 /app/site/var/cache/prod/ContainerCBsis9p/App_KernelProdContainer.php(349): ContainerCBsis9p\\App_KernelProdContainer::getDoctrine_Orm_DefaultEntityManagerService()
#2 /app/site/vendor/symfony/var-exporter/Internal/LazyObjectState.php(61): ContainerCBsis9p\\App_KernelProdContainer::ContainerCBsis9p\\{closure}()
#3 /app/site/vendor/symfony/var-exporter/LazyGhostTrait.php(118): Symfony\\Component\\VarExporter\\Internal\\LazyObjectState->initialize()
#4 /app/site/vendor/doctrine/orm/src/EntityManager.php(529): ContainerCBsis9p\\EntityManagerGhost6410e2e->__get()
#5 /app/site/vendor/doctrine/doctrine-bundle/Registry.php(80): Doctrine\\ORM\\EntityManager->isOpen()
#6 /app/site/vendor/doctrine/doctrine-bundle/Registry.php(66): Doctrine\\Bundle\\DoctrineBundle\\Registry->resetOrClearManager()
#7 /app/site/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php(57): Doctrine\\Bundle\\DoctrineBundle\\Registry->reset()
#8 /app/site/vendor/symfony/http-kernel/Kernel.php(111): Symfony\\Component\\HttpKernel\\DependencyInjection\\ServicesResetter->reset()
#9 /app/site/src/Kernel.php(32): Symfony\\Component\\HttpKernel\\Kernel->boot()
#10 /app/site/vendor/symfony/http-kernel/Kernel.php(180): App\\Kernel->boot()
#11 /app/site/vendor/runtime/frankenphp-symfony/src/Runner.php(38): Symfony\\Component\\HttpKernel\\Kernel->handle()
#12 [internal function]: Runtime\\FrankenPhpSymfony\\Runner->Runtime\\FrankenPhpSymfony\\{closure}()
#13 /app/site/vendor/runtime/frankenphp-symfony/src/Runner.php(45): frankenphp_handle_request()
#14 /app/site/vendor/autoload_runtime.php(29): Runtime\\FrankenPhpSymfony\\Runner->run()
#15 /app/site/public/index.php(5): require_once('...')
#16 {main}
  thrown at /app/site/vendor/doctrine/orm/src/EntityManager.php:114)
[stacktrace]
#0 {main}

How to reproduce

I have no idea how to reproduce it. It happens once in a while, seemingly random. E.g. a failed HTTP request will succeed afterwards, probably related to the usage of frankenphp.

UPDATE: It seems to happen in the request right after a request that closes the EntityManager, e.g. due to Doctrine\\DBAL\\Exception\\UniqueConstraintViolationException

Possible Solution

No response

Additional Context

No response

@NeilPeyssard
Copy link
Contributor

Hello,

Same error in #54228. Any way related ?

@mathieudz
Copy link
Author

@NeilPeyssard You're referencing this issue. You meant another issue?

@NeilPeyssard
Copy link
Contributor

Oups... Monday morning...

Here is the issue: #54104

@mathieudz
Copy link
Author

mathieudz commented Mar 11, 2024

Yes and no.
Yes: identical error message & stack trace when using messenger
No: I don't have any lifecycle handling for doctrine entities.

It seems like the reporter of the other issue avoided the trigger of issue, but didn't not resolve the real problem. I can't see how the fix has anything to do with the exception.

In my case, I was able to reduce the number of exceptions by being a bit more cautious. I have replaced this listener

public function onTerminate(TerminateEvent $event): void
{
    if ($this->entityManager->isOpen()) {
        $this->entityManager->clear();
        $connection = $this->entityManager->getConnection();
        while ($connection->isTransactionActive()) {
            $connection->rollBack();
        }
    }
}

by this

public function onTerminate(TerminateEvent $event): void
{
    $entityManager = $this->entityManager;
    if ($entityManager instanceof LazyObjectInterface && !$entityManager->isLazyObjectInitialized()) {
        return;
    }
    if ($entityManager->isOpen()) {
        $entityManager->clear();
        $connection = $entityManager->getConnection();
        while ($connection->isTransactionActive()) {
            $connection->rollBack();
        }
    }
}

It was the more frequent place it failed (isOpen())
It is not a real fix though, I just avoid triggering a call on the EntityManager when the lazy object is not initialized (and thus not open anyway).

@mathieudz
Copy link
Author

The exception when using messenger could be solved in the same way: first check if the lazy object is initialized before checking if it's open. It is not a solution for my first example, where it fails in a HTTP request though.

@mathieudz
Copy link
Author

mathieudz commented Mar 11, 2024

It seems heavily correlated with database errors impacting the doctrine entity manager. I have found the same pattern in processing of my message handlers. First a unique constraint error, then this readonly error.
I think it's similar to the other issue now: the reporter forgot to enable lifecycle callbacks, which resulted in NOT NULL columns not have a value, resulting in a database constraint problem, closing the entity manager.
So the reproducer should be: trigger a database constraint error and try to use the entity manager afterwards. E.g. by using a process manager like frankenphp, or by processing messages with messenger. In the last case, the automatic resetting of services will trigger the entity manager it by calling isOpen.

@mathieudz
Copy link
Author

mathieudz commented Mar 11, 2024

I was able to reproduce it reliably.
I create a message

class TestMessage
{
}

.. and a message handler that tries to create an incomplete entity

#[AsMessageHandler]
readonly final class TestMessageHandler
{
    public function __construct(private EntityManagerInterface $entityManager, private LoggingService $loggingService)
    {
    }

    public function __invoke(TestMessage $message): void
    {
        $user = $this->entityManager->find(User::class, 1);
        Assertion::notNull($user);
        $this->loggingService->logEvent('Automated cleanup');
        $artist = new Artist('Elton John', Artist::TYPE_PERSON, $user);
        $this->entityManager->persist($artist);
        $this->entityManager->flush();
    }
}

I trigger it async

framework:
    messenger:
        failure_transport: failed

        transports:
            async: '%env(MESSENGER_TRANSPORT_DSN)%'
            failed: 'doctrine://default?queue_name=failed'

        routing:
            'App\Message\TestMessage': async

In the messenger output you can see that the error occurs on the first retry:

09:46:12 INFO      [messenger] Received message App\Message\TestMessage ["class" => "App\Message\TestMessage"]
09:46:12 WARNING   [messenger] Error thrown while handling message App\Message\TestMessage. Sending for retry #1 using 1000 ms delay. Error: "Handling "App\Message\TestMessage" failed: An exception occurred while executing a query: SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column "created_by" violates not-null constraint\nDETAIL:  Failing row contains (null, 2024-03-11 10:46:12.652858+01, null, null, 0, 227655, artist, t, null, Elton John, null, null, null, null, null, elton john, elton john, 1, 1, null, null, null, null, null, null, null, person, null, null, null, null, null, f, null)." ["class" => "App\Message\TestMessage","retryCount" => 1,"delay" => 1000,"error" => """  Handling "App\Message\TestMessage" failed: An exception occurred while executing a query: SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column "created_by" violates not-null constraint\n  DETAIL:  Failing row contains (null, 2024-03-11 10:46:12.652858+01, null, null, 0, 227655, artist, t, null, Elton John, null, null, null, null, null, elton john, elton john, 1, 1, null, null, null, null, null, null, null, person, null, null, null, null, null, f, null).  ""","exception" => Symfony\Component\Messenger\Exception\HandlerFailedException�]8;;file:///home/mathieu/site/vendor/symfony/messenger/Exception/HandlerFailedException.php#L16�\^�]8;;�\ { …}]
09:46:13 INFO      [messenger] Received message App\Message\TestMessage ["class" => "App\Message\TestMessage"]
09:46:13 WARNING   [messenger] Error thrown while handling message App\Message\TestMessage. Sending for retry #2 using 2000 ms delay. Error: "Handling "App\Message\TestMessage" failed: Cannot modify readonly property Doctrine\ORM\EntityManager::$conn" ["class" => "App\Message\TestMessage","retryCount" => 2,"delay" => 2000,"error" => "Handling "App\Message\TestMessage" failed: Cannot modify readonly property Doctrine\ORM\EntityManager::$conn","exception" => Symfony\Component\Messenger\Exception\HandlerFailedException�]8;;file:///home/mathieu/site/vendor/symfony/messenger/Exception/HandlerFailedException.php#L16�\^�]8;;�\ { …}]
In EntityManager.php line 114:
                                                                     
  [Error]                                                            
  Cannot modify readonly property Doctrine\ORM\EntityManager::$conn  
                                                                     

Exception trace:
  at /home/mathieu/site/vendor/doctrine/orm/src/EntityManager.php:114
 Doctrine\ORM\EntityManager->__construct() at /home/mathieu/site/var/cache/dev/ContainerLOaKH9W/App_KernelDevDebugContainer.php:1008
 ContainerLOaKH9W\App_KernelDevDebugContainer::getDoctrine_Orm_DefaultEntityManagerService() at /home/mathieu/site/var/cache/dev/ContainerLOaKH9W/App_KernelDevDebugContainer.php:948
 ContainerLOaKH9W\App_KernelDevDebugContainer::ContainerLOaKH9W\{closure}() at /home/mathieu/site/vendor/symfony/var-exporter/Internal/LazyObjectState.php:61
 Symfony\Component\VarExporter\Internal\LazyObjectState->initialize() at /home/mathieu/site/vendor/symfony/var-exporter/LazyGhostTrait.php:118
 ContainerLOaKH9W\EntityManagerGhostEbeb667->__get() at /home/mathieu/site/vendor/doctrine/orm/src/EntityManager.php:529
 Doctrine\ORM\EntityManager->isOpen() at /home/mathieu/site/vendor/doctrine/doctrine-bundle/Registry.php:80
 Doctrine\Bundle\DoctrineBundle\Registry->resetOrClearManager() at /home/mathieu/site/vendor/doctrine/doctrine-bundle/Registry.php:66
 Doctrine\Bundle\DoctrineBundle\Registry->reset() at /home/mathieu/site/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php:57
 Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter->reset() at /home/mathieu/site/vendor/symfony/messenger/EventListener/ResetServicesListener.php:34
 Symfony\Component\Messenger\EventListener\ResetServicesListener->resetServices() at /home/mathieu/site/vendor/symfony/event-dispatcher/Debug/WrappedListener.php:116
 Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke() at /home/mathieu/site/vendor/symfony/event-dispatcher/EventDispatcher.php:206
 Symfony\Component\EventDispatcher\EventDispatcher->callListeners() at /home/mathieu/site/vendor/symfony/event-dispatcher/EventDispatcher.php:56
 Symfony\Component\EventDispatcher\EventDispatcher->dispatch() at /home/mathieu/site/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php:127
 Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch() at /home/mathieu/site/vendor/symfony/messenger/Worker.php:110
 Symfony\Component\Messenger\Worker->run() at /home/mathieu/site/vendor/symfony/messenger/Command/ConsumeMessagesCommand.php:235
 Symfony\Component\Messenger\Command\ConsumeMessagesCommand->execute() at /home/mathieu/site/vendor/symfony/console/Command/Command.php:279
 Symfony\Component\Console\Command\Command->run() at /home/mathieu/site/vendor/symfony/console/Application.php:1049
 Symfony\Component\Console\Application->doRunCommand() at /home/mathieu/site/vendor/symfony/framework-bundle/Console/Application.php:125
 Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /home/mathieu/site/vendor/symfony/console/Application.php:318
 Symfony\Component\Console\Application->doRun() at /home/mathieu/site/vendor/symfony/framework-bundle/Console/Application.php:79
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /home/mathieu/site/vendor/symfony/console/Application.php:169
 Symfony\Component\Console\Application->run() at /home/mathieu/site/vendor/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php:49
 Symfony\Component\Runtime\Runner\Symfony\ConsoleApplicationRunner->run() at /home/mathieu/site/vendor/autoload_runtime.php:29
 require_once() at /home/mathieu/site/bin/console:11

@NeilPeyssard
Copy link
Contributor

NeilPeyssard commented Mar 11, 2024

I tried to fix it but unfortunately it's way above my skills 😄

Something is happening during the services resetting, and as you said, when the connection was closed, an error is thrown and the worker stops. Not really sure, but it may be a Doctrine bug (e.g. not a Symfony issue).

I have created a reproducer for those who have an idea about what is wrong here.

@mathieudz
Copy link
Author

mathieudz commented Mar 11, 2024

Should I already log this at Doctrine so they can have a look at it too? I think it's not a pure Symfony or Doctrine bug, but rather how they work together (and therefore rather a Symfony issue after all).

@antonzapevalov
Copy link

Same problem with entityManager and messages...

@curry684
Copy link
Contributor

Running into the same issue with long lived Messenger worker processes after upgrade to ORM 3. The lazy ghosts are reset between messages and reinstating them causes it to crash. Line 114 of the Entity Manager is the constructor:

    public function __construct(
        private readonly Connection $conn,
        private readonly Configuration $config,
        EventManager|null $eventManager = null,
    ) {

I'm also not really sure if this is an issue with how the lazy ghosts work or how Doctrine uses them for this, I have no issue with other services. It seems to be a quite fundamental oversight in how lazy ghosts manually invoke the constructor on a living object but didn't really dive into it yet.

@akhx
Copy link

akhx commented Mar 22, 2024

Got the same error when calling resetManager() when EntityManager is closed

example repository

use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

class ShortLinkRepository extends ServiceEntityRepository
{
    public function __construct(private readonly ManagerRegistry $registry)
    {
        parent::__construct($this->registry, ShortLink::class);
    }

    public function create(ShortLink $entity): void
    {
        $this->checkEntityManager();

        $this->getEntityManager()->persist($entity);
        $this->getEntityManager()->flush();
    }

    private function checkEntityManager(): void
    {
        if ($this->getEntityManager()->isOpen()) {
            return;
        }

        $this->registry->resetManager();
    }
}

trace

#0 /var/www/var/cache/dev/Container6NxX5Sl/App_KernelDevDebugContainer.php(709): Doctrine\\ORM\\EntityManager->__construct(Object(Doctrine\\DBAL\\Connection), Object(Doctrine\\ORM\\Configuration), Object(Symfony\\Bridge\\Doctrine\\ContainerAwareEventManager))
#1 /var/www/var/cache/dev/Container6NxX5Sl/App_KernelDevDebugContainer.php(644): Container6NxX5Sl\\App_KernelDevDebugContainer::getDoctrine_Orm_DefaultEntityManagerService(Object(Container6NxX5Sl\\App_KernelDevDebugContainer), Object(Container6NxX5Sl\\EntityManagerGhostEbeb667))
#2 /var/www/vendor/symfony/var-exporter/Internal/LazyObjectState.php(61): Container6NxX5Sl\\App_KernelDevDebugContainer::Container6NxX5Sl\\{closure}(Object(Container6NxX5Sl\\EntityManagerGhostEbeb667))
#3 /var/www/vendor/symfony/var-exporter/LazyGhostTrait.php(118): Symfony\\Component\\VarExporter\\Internal\\LazyObjectState->initialize(Object(Container6NxX5Sl\\EntityManagerGhostEbeb667), 'closed', 'Doctrine\\\\ORM\\\\En...')
#4 /var/www/vendor/doctrine/orm/src/EntityManager.php(522): Container6NxX5Sl\\EntityManagerGhostEbeb667->__get('closed')
#5 /var/www/vendor/doctrine/orm/src/EntityManager.php(432): Doctrine\\ORM\\EntityManager->errorIfClosed()
#6 /var/www/src/Infrastructure/Symfony/Repository/ShortLinkRepository.php(103): Doctrine\\ORM\\EntityManager->persist(Object(App\\Domain\\Entity\\ShortLink))
#7 /var/www/src/Application/UseCase/ShortLink/Create/CreateShortLinkUseCase.php(48): App\\Infrastructure\\Symfony\\Repository\\ShortLinkRepository->create(Object(App\\Domain\\Entity\\ShortLink))
#8 /var/www/src/Infrastructure/Symfony/Controller/Api/v1/Admin/ShortLink/Create/CreateShortLinkController.php(58): App\\Application\\UseCase\\ShortLink\\Create\\CreateShortLinkUseCase->handle(Object(App\\Application\\UseCase\\ShortLink\\Create\\Boundary\\CreateShortLinkRequest))
#9 /var/www/vendor/symfony/http-kernel/HttpKernel.php(178): App\\Infrastructure\\Symfony\\Controller\\Api\\v1\\Admin\\ShortLink\\Create\\CreateShortLinkController->__invoke(Object(App\\Infrastructure\\Symfony\\Controller\\Api\\v1\\Admin\\ShortLink\\Create\\Dto\\CreateShortLinkInDto), Object(App\\Application\\UseCase\\ShortLink\\Create\\CreateShortLinkUseCase))
#10 /var/www/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\\Component\\HttpKernel\\HttpKernel->handleRaw(Object(Symfony\\Component\\HttpFoundation\\Request), 1)
#11 /var/www/vendor/symfony/http-kernel/Kernel.php(185): Symfony\\Component\\HttpKernel\\HttpKernel->handle(Object(Symfony\\Component\\HttpFoundation\\Request), 1, true)
#12 /var/www/vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php(35): Symfony\\Component\\HttpKernel\\Kernel->handle(Object(Symfony\\Component\\HttpFoundation\\Request))
#13 /var/www/vendor/autoload_runtime.php(29): Symfony\\Component\\Runtime\\Runner\\Symfony\\HttpKernelRunner->run()
#14 /var/www/public/index.php(9): require_once('/var/www/vendor...')
#15 {main}

@Snowbaha
Copy link

I have the same issue when I upgrated ORM 2.19 to 3.1 and using Messenging with Scheduler.
It is so strange...

@KamikX
Copy link

KamikX commented Apr 15, 2024

@mathieudz You have two problem first is Not null violation on column created_by , try fix this and maybe problem Cannot modify readonly property Doctrine\ORM\EntityManager::$conn will gone, I had a same problem with a wrong date type, after fix this problem, everything started working.

I was able to reproduce it reliably. I create a message

class TestMessage
{
}

.. and a message handler that tries to create an incomplete entity

#[AsMessageHandler]
readonly final class TestMessageHandler
{
    public function __construct(private EntityManagerInterface $entityManager, private LoggingService $loggingService)
    {
    }

    public function __invoke(TestMessage $message): void
    {
        $user = $this->entityManager->find(User::class, 1);
        Assertion::notNull($user);
        $this->loggingService->logEvent('Automated cleanup');
        $artist = new Artist('Elton John', Artist::TYPE_PERSON, $user);
        $this->entityManager->persist($artist);
        $this->entityManager->flush();
    }
}

I trigger it async

framework:
    messenger:
        failure_transport: failed

        transports:
            async: '%env(MESSENGER_TRANSPORT_DSN)%'
            failed: 'doctrine://default?queue_name=failed'

        routing:
            'App\Message\TestMessage': async

In the messenger output you can see that the error occurs on the first retry:

09:46:12 INFO      [messenger] Received message App\Message\TestMessage ["class" => "App\Message\TestMessage"]
09:46:12 WARNING   [messenger] Error thrown while handling message App\Message\TestMessage. Sending for retry #1 using 1000 ms delay. Error: "Handling "App\Message\TestMessage" failed: An exception occurred while executing a query: SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column "created_by" violates not-null constraint\nDETAIL:  Failing row contains (null, 2024-03-11 10:46:12.652858+01, null, null, 0, 227655, artist, t, null, Elton John, null, null, null, null, null, elton john, elton john, 1, 1, null, null, null, null, null, null, null, person, null, null, null, null, null, f, null)." ["class" => "App\Message\TestMessage","retryCount" => 1,"delay" => 1000,"error" => """  Handling "App\Message\TestMessage" failed: An exception occurred while executing a query: SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column "created_by" violates not-null constraint\n  DETAIL:  Failing row contains (null, 2024-03-11 10:46:12.652858+01, null, null, 0, 227655, artist, t, null, Elton John, null, null, null, null, null, elton john, elton john, 1, 1, null, null, null, null, null, null, null, person, null, null, null, null, null, f, null).  ""","exception" => Symfony\Component\Messenger\Exception\HandlerFailedException�]8;;file:///home/mathieu/site/vendor/symfony/messenger/Exception/HandlerFailedException.php#L16�\^�]8;;�\ { …}]
09:46:13 INFO      [messenger] Received message App\Message\TestMessage ["class" => "App\Message\TestMessage"]
09:46:13 WARNING   [messenger] Error thrown while handling message App\Message\TestMessage. Sending for retry #2 using 2000 ms delay. Error: "Handling "App\Message\TestMessage" failed: Cannot modify readonly property Doctrine\ORM\EntityManager::$conn" ["class" => "App\Message\TestMessage","retryCount" => 2,"delay" => 2000,"error" => "Handling "App\Message\TestMessage" failed: Cannot modify readonly property Doctrine\ORM\EntityManager::$conn","exception" => Symfony\Component\Messenger\Exception\HandlerFailedException�]8;;file:///home/mathieu/site/vendor/symfony/messenger/Exception/HandlerFailedException.php#L16�\^�]8;;�\ { …}]
In EntityManager.php line 114:
                                                                     
  [Error]                                                            
  Cannot modify readonly property Doctrine\ORM\EntityManager::$conn  
                                                                     

Exception trace:
  at /home/mathieu/site/vendor/doctrine/orm/src/EntityManager.php:114
 Doctrine\ORM\EntityManager->__construct() at /home/mathieu/site/var/cache/dev/ContainerLOaKH9W/App_KernelDevDebugContainer.php:1008
 ContainerLOaKH9W\App_KernelDevDebugContainer::getDoctrine_Orm_DefaultEntityManagerService() at /home/mathieu/site/var/cache/dev/ContainerLOaKH9W/App_KernelDevDebugContainer.php:948
 ContainerLOaKH9W\App_KernelDevDebugContainer::ContainerLOaKH9W\{closure}() at /home/mathieu/site/vendor/symfony/var-exporter/Internal/LazyObjectState.php:61
 Symfony\Component\VarExporter\Internal\LazyObjectState->initialize() at /home/mathieu/site/vendor/symfony/var-exporter/LazyGhostTrait.php:118
 ContainerLOaKH9W\EntityManagerGhostEbeb667->__get() at /home/mathieu/site/vendor/doctrine/orm/src/EntityManager.php:529
 Doctrine\ORM\EntityManager->isOpen() at /home/mathieu/site/vendor/doctrine/doctrine-bundle/Registry.php:80
 Doctrine\Bundle\DoctrineBundle\Registry->resetOrClearManager() at /home/mathieu/site/vendor/doctrine/doctrine-bundle/Registry.php:66
 Doctrine\Bundle\DoctrineBundle\Registry->reset() at /home/mathieu/site/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php:57
 Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter->reset() at /home/mathieu/site/vendor/symfony/messenger/EventListener/ResetServicesListener.php:34
 Symfony\Component\Messenger\EventListener\ResetServicesListener->resetServices() at /home/mathieu/site/vendor/symfony/event-dispatcher/Debug/WrappedListener.php:116
 Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke() at /home/mathieu/site/vendor/symfony/event-dispatcher/EventDispatcher.php:206
 Symfony\Component\EventDispatcher\EventDispatcher->callListeners() at /home/mathieu/site/vendor/symfony/event-dispatcher/EventDispatcher.php:56
 Symfony\Component\EventDispatcher\EventDispatcher->dispatch() at /home/mathieu/site/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php:127
 Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch() at /home/mathieu/site/vendor/symfony/messenger/Worker.php:110
 Symfony\Component\Messenger\Worker->run() at /home/mathieu/site/vendor/symfony/messenger/Command/ConsumeMessagesCommand.php:235
 Symfony\Component\Messenger\Command\ConsumeMessagesCommand->execute() at /home/mathieu/site/vendor/symfony/console/Command/Command.php:279
 Symfony\Component\Console\Command\Command->run() at /home/mathieu/site/vendor/symfony/console/Application.php:1049
 Symfony\Component\Console\Application->doRunCommand() at /home/mathieu/site/vendor/symfony/framework-bundle/Console/Application.php:125
 Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /home/mathieu/site/vendor/symfony/console/Application.php:318
 Symfony\Component\Console\Application->doRun() at /home/mathieu/site/vendor/symfony/framework-bundle/Console/Application.php:79
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /home/mathieu/site/vendor/symfony/console/Application.php:169
 Symfony\Component\Console\Application->run() at /home/mathieu/site/vendor/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php:49
 Symfony\Component\Runtime\Runner\Symfony\ConsoleApplicationRunner->run() at /home/mathieu/site/vendor/autoload_runtime.php:29
 require_once() at /home/mathieu/site/bin/console:11

@mathieudz
Copy link
Author

mathieudz commented Apr 15, 2024

@KamikX That not-null violation is just a reproducer for this bug. I cannot guarantee that I never have such DB errors, so this bug will continue to occur.

@KamikX
Copy link

KamikX commented Apr 15, 2024

@mathieudz Sorry, you are right, I was only concentrating on solving my current problem in the code and didn't read the whole context.

@CViniciusSDias
Copy link

I see the same problem with Swoole Runtime.

Steps to reproduce:

  1. Use a stateful runtime (Swoole, FrankenPHP, or even running the consumers);
  2. Get a repository in the constructor of the handler (either the controller or listener);
  3. Execute it at least twice. It will fail with the error.

@RafaelKr
Copy link

I have the same problem in a Symfony Worker (message consumer).

@tyteen4a03
Copy link

tyteen4a03 commented Apr 22, 2024

Also running this error when trying to do this in Symfony:

    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, NpScore::class);
        $this->registry = $registry;
    }

    public function save(NpScore $npScore): void
    {
        $em = $this->getEntityManager();
        if (!$em->isOpen()) {
            $this->registry->resetManager();
            $em = $this->getEntityManager();
        }
        $em->persist($npScore);
        $em->flush();
    }

@ReSpawN
Copy link

ReSpawN commented Apr 24, 2024

When debugging this error went way deeper than at first glance. The root cause, in my case, was an already existing incremental value on a sequence. I use PostgreSQL and I injected some rows manually, not knowing that Datagrip wouldn't auto-increment my IDs. Then using debug/verbose output in the console the message (through messenger:consume) was clearly visible.

I hope this helps someone.

@JeroenMoonen
Copy link

JeroenMoonen commented May 7, 2024

I had the same issue. For me, I had an incorrect Doctrine mapping: a Types::TEXT property should be Types::BLOB. After fixing this issue, the problem resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests