Doctrine ORM: Transaction commit fails after rollback in batch loop (Symfony 5.4, PHP 7.4)

I’m running a batch process in Symfony 5.4.48 (PHP 7.4.30, Doctrine ORM 2.20.3) where I need to handle database transactions per iteration. If a business condition fails, I want to rollback the transaction and continue to the next item. However, after a rollback, the next iteration fails with:

Transaction commit failed because the transaction has been marked for rollback only.

Here’s a simplified version of my code:

<?php
foreach ($items as $item) {
    $em = $doctrine->getManager();
    $connection = $em->getConnection();
    $connection->beginTransaction();
    try {
        // ... business logic ...
        if ($shouldRollback) {
            $connection->rollBack();
            $doctrine->resetManager();
            continue;
        }
        $connection->commit();
    } catch (Throwable $e) {
        if ($connection->isTransactionActive()) {
            $connection->rollBack();
        }
        $doctrine->resetManager();
        continue;
    }
}

Even after calling $doctrine->resetManager(), the next $em and $connection seem to be in a “rollback only” state, and commit() fails.

Environment:

  • Symfony: 5.4.48
  • Doctrine ORM: 2.20.3
  • PHP: 7.4.30
  • OS: Windows

What I’ve tried:

  • Resetting the EntityManager with $doctrine->resetManager()
  • Reacquiring the EntityManager and Connection after rollback
  • Checking transaction state with $connection->isRollbackOnly()

Questions:

  • Is this the expected behavior for Doctrine ORM?
  • How can I fully reset the EntityManager/Connection so that the next transaction works?
  • Is there a recommended pattern for batch processing with per-iteration transactions in Doctrine?