[symfony] The EntityManager is closed

[Doctrine\ORM\ORMException]   
The EntityManager is closed.  

After I get a DBAL exception when inserting data, EntityManager closes and I'm not able to reconnect it.

I tried like this but it didn't get a connection.

$this->em->close();
$this->set('doctrine.orm.entity_manager', null);
$this->set('doctrine.orm.default_entity_manager', null);
$this->get('doctrine')->resetEntityManager();
$this->em = $this->get('doctrine')->getEntityManager();

Anyone an idea how to reconnect?

This question is related to symfony orm doctrine-orm entitymanager

The answer is


I had this issue. This how I fixed it.

The connection seems to close while trying to flush or persist. Trying to reopen it is a bad choice because creates new issues. I tryed to understand why the connection was closed and found that I was doing too many modifications before the persist.

persist() earlier solved the issue.


This is really old issue, but I just had similar problem. I was doing something like this :

// entity
$entityOne = $this->em->find(Parent::class, 1);

// do something on other entites (SomeEntityClass)
$this->em->persist($entity);
$this->em->flush();
$this->em->clear();

// and at end I was trying to save changes to first one by
$this->em->persist($entityOne);
$this->em->flush();
$this->em->clear();

Problem was that clear detach all entities including the first one and throw error The EntityManager is closed.

In my case solution was to just do clear on distinct type of Entity and leave $entityOne still under EM:

$this->em->clear(SomeEntityClass::class);

Symfony 2.0:

$em = $this->getDoctrine()->resetEntityManager();

Symfony 2.1+:

$em = $this->getDoctrine()->resetManager();

I had the same error using Symfony 5 / Doctrine 2. One of my fields was named using a MySQL reserved word "order", causing a DBALException. When you want to use a reserved word, you have to escape it's name using back-ticks. In annotation form :

@ORM\Column(name="`order`", type="integer", nullable=false)

this how you reset the enitityManager in Symfony3. It should reopen the em if it has been closed:

In a Controller:

$em = $this->getDoctrine()->resetEntityManager();

In a service:

  if (!$this->em->isOpen()) {
        $this->managerRegistry->resetManager('managername');
        $this->em = $this->managerRegistry->getManager('default');
    }

    $this->em->persist(...);

Don't forget to inject the '@doctrine' as a service argument in service.yml!

I'm wondering, if this problem happens if different methodes concurrently tries to access the same entity at the same time?


Same problem, solved with a simple code refactoring. The problem is sometime present when a required field is null, before do anithing, try to refactor your code. A better workflow can solve the problem.


This is how I solved the Doctrine "The EntityManager is closed." issue. Basically each time there's an exception (i.e. duplicate key) or not providing data for a mandatory column will cause Doctrine to close the Entity Manager. If you still want to interact with the database you have to reset the Entity Manger by calling the resetManager() method as mentioned by JGrinon.

In my application I was running multiple RabbitMQ consumers that were all doing the same thing: checking if an entity was there in the database, if yes return it, if not create it and then return it. In the few milliseconds between checking if that entity already existed and creating it another consumer happened to do the same and created the missing entity making the other consumer incur in a duplicate key exception (race condition).

This led to a software design problem. Basically what I was trying to do was creating all the entities in one transaction. This may feel natural to most but was definitely conceptually wrong in my case. Consider the following problem: I had to store a football Match entity which had these dependencies.

  • a group (e.g. Group A, Group B...)
  • a round (e.g. Semi-finals...)
  • a venue (i.e. stadium where the match is taking place)
  • a match status (e.g. half time, full time)
  • the two teams playing the match
  • the match itself

Now, why the venue creation should be in the same transaction as the match? It could be that I've just received a new venue that it's not in my database so I have to create it first. But it could also be that that venue may host another match so another consumer will probably try to create it as well at the same time. So what I had to do was create all the dependencies first in separate transactions making sure I was resetting the entity manager in a duplicate key exception. I'd say that all the entities in there beside the match could be defined as "shared" because they could potentially be part of other transactions in other consumers. Something that is not "shared" in there is the match itself that won't likely be created by two consumers at the same time. So in the last transaction I expect to see just the match and the relation between the two teams and the match.

All of this also led to another issue. If you reset the Entity Manager, all the objects that you've retrieved before resetting are for Doctrine totally new. So Doctrine won't try to run an UPDATE on them but an INSERT! So make sure you create all your dependencies in logically correct transactions and then retrieve all your objects back from the database before setting them to the target entity. Consider the following code as an example:

$group = $this->createGroupIfDoesNotExist($groupData);

$match->setGroup($group); // this is NOT OK!

$venue = $this->createVenueIfDoesNotExist($venueData);

$round = $this->createRoundIfDoesNotExist($roundData);

/**
 * If the venue creation generates a duplicate key exception
 * we are forced to reset the entity manager in order to proceed
 * with the round creation and so we'll loose the group reference.
 * Meaning that Doctrine will try to persist the group as new even
 * if it's already there in the database.
 */

So this is how I think it should be done.

$group = $this->createGroupIfDoesNotExist($groupData); // first transaction, reset if duplicated
$venue = $this->createVenueIfDoesNotExist($venueData); // second transaction, reset if duplicated
$round = $this->createRoundIfDoesNotExist($roundData); // third transaction, reset if duplicated

// we fetch all the entities back directly from the database
$group = $this->getGroup($groupData);
$venue = $this->getVenue($venueData);
$round = $this->getGroup($roundData);

// we finally set them now that no exceptions are going to happen
$match->setGroup($group);
$match->setVenue($venue);
$match->setRound($round);

// match and teams relation...
$matchTeamHome = new MatchTeam();
$matchTeamHome->setMatch($match);
$matchTeamHome->setTeam($teamHome);

$matchTeamAway = new MatchTeam();
$matchTeamAway->setMatch($match);
$matchTeamAway->setTeam($teamAway);

$match->addMatchTeam($matchTeamHome);
$match->addMatchTeam($matchTeamAway);

// last transaction!
$em->persist($match);
$em->persist($matchTeamHome);
$em->persist($matchTeamAway);
$em->flush();

I hope it helps :)


I faced the same problem while testing the changes in Symfony 4.3.2

I lowered the log level to INFO

And ran the test again

And the logged showed this:

console.ERROR: Error thrown while running command "doctrine:schema:create". Message: "[Semantical Error] The annotation "@ORM\Id" in property App\Entity\Common::$id was never imported. Did you maybe forget to add a "use" statement for this annotation?" {"exception":"[object] (Doctrine\\Common\\Annotations\\AnnotationException(code: 0): [Semantical Error] The annotation \"@ORM\\Id\" in property App\\Entity\\Common::$id was never imported. Did you maybe forget to add a \"use\" statement for this annotation? at C:\\xampp\\htdocs\\dirty7s\\vendor\\doctrine\\annotations\\lib\\Doctrine\\Common\\Annotations\\AnnotationException.php:54)","command":"doctrine:schema:create","message":"[Semantical Error] The annotation \"@ORM\\Id\" in property App\\Entity\\Common::$id was never imported. Did you maybe forget to add a \"use\" statement for this annotation?"} []

This means that some error in the code causes the:

Doctrine\ORM\ORMException: The EntityManager is closed.

So it is a good idea to check the log


I faced the same problem. After looking at several places here is how I dealt with it.

//function in some model/utility
function someFunction($em){
    try{
        //code which may throw exception and lead to closing of entity manager
    }
    catch(Exception $e){
        //handle exception
        return false;
    }
    return true;
}

//in controller assuming entity manager is in $this->em 
$result = someFunction($this->em);
if(!$result){
    $this->getDoctrine()->resetEntityManager();
    $this->em = $this->getDoctrine()->getManager();
}

Hope this helps someone!


// first need to reset current manager
$em->resetManager();
// and then get new
$em = $this->getContainer()->get("doctrine");
// or in this way, depending of your environment:
$em = $this->getDoctrine();

You can reset your EM so

// reset the EM and all aias
$container = $this->container;
$container->set('doctrine.orm.entity_manager', null);
$container->set('doctrine.orm.default_entity_manager', null);
// get a fresh EM
$em = $this->getDoctrine()->getManager();

Symfony v4.1.6

Doctrine v2.9.0

Process inserting duplicates in a repository

  1. Get access a registry in your repo


    //begin of repo
    
    /** @var RegistryInterface */
    protected $registry;
    
    public function __construct(RegistryInterface $registry)
    {
        $this->registry = $registry;
        parent::__construct($registry, YourEntity::class);
    }

  1. Wrap risky code into transaction and reset manager in case of exception


    //in repo method
    $em = $this->getEntityManager();
    
    $em->beginTransaction();
    try {
        $em->persist($yourEntityThatCanBeDuplicate);
        $em->flush();
        $em->commit();
    
    } catch (\Throwable $e) {
        //Rollback all nested transactions
        while ($em->getConnection()->getTransactionNestingLevel() > 0) {
            $em->rollback();
        }
        
        //Reset the default em
        if (!$em->isOpen()) {
            $this->registry->resetManager();
        }
    }


For what it's worth I found this issue was happening in a batch import command because of a try/catch loop catching an SQL error (with em->flush()) that I didn't do anything about. In my case it was because I was trying to insert a record with a non-nullable property left as null.

Typically this would cause a critical exception to happen and the command or controller to halt, but I was just logging this problem instead and carrying on. The SQL error had caused the entity manager to close.

Check your dev.log file for any silly SQL errors like this as it could be your fault. :)


I found an interesting article about this problem

if (!$entityManager->isOpen()) {
  $entityManager = $entityManager->create(
    $entityManager->getConnection(), $entityManager->getConfiguration());
}

Doctrine 2 Exception EntityManager is closed


My solution.

Before doing anything check:

if (!$this->entityManager->isOpen()) {
    $this->entityManager = $this->entityManager->create(
        $this->entityManager->getConnection(),
        $this->entityManager->getConfiguration()
    );
}

All entities will be saved. But it is handy for particular class or some cases. If you have some services with injected entitymanager, it still be closed.


In controller.

Exception closes the Entity Manager. This makes troubles for bulk insert. To continue, need to redefine it.

/** 
* @var  \Doctrine\ORM\EntityManager
*/
$em = $this->getDoctrine()->getManager();

foreach($to_insert AS $data)
{
    if(!$em->isOpen())
    {
        $this->getDoctrine()->resetManager();
        $em = $this->getDoctrine()->getManager();
    }

  $entity = new \Entity();
  $entity->setUniqueNumber($data['number']);
  $em->persist($entity);

  try
  {
    $em->flush();
    $counter++;
  }
  catch(\Doctrine\DBAL\DBALException $e)
  {
    if($e->getPrevious()->getCode() != '23000')
    {   
      /**
      * if its not the error code for a duplicate key 
      * value then rethrow the exception
      */
      throw $e;
    }
    else
    {
      $duplication++;
    }               
  }                      
}

In Symfony 4.2+ you have to use the package:

composer require symfony/proxy-manager-bridge

otherwiese you get the exception:

Resetting a non-lazy manager service is not supported. Declare the "doctrine.orm.default_entity_manager" service as lazy.  

Than you can reset the entityManager like this:

services.yaml:

App\Foo:
    - '@doctrine.orm.entity_manager'
    - '@doctrine'

Foo.php:

use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\DBAL\DBALException;
use Doctrine\ORM\EntityManagerInterface;


 try {
    $this->entityManager->persist($entity);
    $this->entityManager->flush();
} catch (DBALException $e) {
    if (!$this->entityManager->isOpen()) {
        $this->entityManager = $this->doctrine->resetManager();
    }
}

Examples related to symfony

Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? Composer require runs out of memory. PHP Fatal error: Allowed memory size of 1610612736 bytes exhausted SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES) symfony2 The CSRF token is invalid. Please try to resubmit the form What is the difference between .yaml and .yml extension? How can I use break or continue within for loop in Twig template? Running Composer returns: "Could not open input file: composer.phar" Symfony2 and date_default_timezone_get() - It is not safe to rely on the system's timezone settings Symfony - generate url with parameter in controller Call PHP function from Twig template

Examples related to orm

How to select specific columns in laravel eloquent Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] How to query between two dates using Laravel and Eloquent? Laravel - Eloquent "Has", "With", "WhereHas" - What do they mean? How to Make Laravel Eloquent "IN" Query? How to auto generate migrations with Sequelize CLI from Sequelize models? How to fix org.hibernate.LazyInitializationException - could not initialize proxy - no Session Select the first 10 rows - Laravel Eloquent How to make join queries using Sequelize on Node.js What is Persistence Context?

Examples related to doctrine-orm

How to sort findAll Doctrine's method? Doctrine query builder using inner join with conditions How to do left join in Doctrine? How to use a findBy method with comparative criteria The EntityManager is closed Doctrine findBy 'does not equal' How to order results with findBy() in Doctrine Select entries between dates in doctrine 2 Get single row result with Doctrine NativeQuery Count Rows in Doctrine QueryBuilder

Examples related to entitymanager

What does EntityManager.flush do and why do I need to use it? JPA With Hibernate Error: [PersistenceUnit: JPA] Unable to build EntityManagerFactory The EntityManager is closed What is the best way to update the entity in JPA Create JPA EntityManager without persistence.xml configuration file JPA EntityManager: Why use persist() over merge()?