PHP 8: "PDOException: There is no active transaction" #7395

Closed
opened 2026-01-22 15:51:11 +01:00 by admin · 0 comments
Owner

Originally created by @JarJak on GitHub (Jul 3, 2024).

Bug Report

I am not sure if this is bug for ORM or DBAL.

Versions:
PHP 8.2
ORM 2.19.5
DBAL 3.8.6
Symfony 8.2
Postgres 13.7

DBAL config:

                'connections' => [
                    'default' => [
                        'url' => '%env(resolve:DATABASE_URL)%',
                        'use_savepoints' => true,
                        'driver' => 'pdo_pgsql',
                    ],
                ],

Summary

When using transactions inside code, when exception occurs "entitymanager is closed" and transaction is rollbacked, that results in "PDOException: There is no active transaction" error.

I have seen similar bugs reported, but they either happen with MySQL/MariaDB or in migrations. For me this happens with Postgres and in regular app code.

Even though before rollbacking, Doctrine checks if it has a flag for active transaction before sending ROLLBACK sql to the database, for some reason this does not always work.

Code fragment from UoW commit() method (which is always called in flush() regardless of transaction mode): https://github.com/doctrine/orm/blob/3.2.x/src/UnitOfWork.php#L439

        } catch (Throwable $e) {
            // exception "entitymanager is closed" caught
            $this->em->close(); // closes em (but is already closed)

            if ($conn->isTransactionActive()) { // this for some reason returns true
                $conn->rollBack(); // this fails with "no active transaction"
            }

            $this->afterTransactionRolledBack();

            throw $e;
        }

Proposed solution

One "dirty and hacky" way to fix it would be to add another try/catch inside the code above:

        } catch (Throwable $e) {
            // exception "entitymanager is closed" caught
            $this->em->close(); // closes em (but is already closed)

            if ($conn->isTransactionActive()) { // this for some reason returns true
                try {
                	$conn->rollBack(); // this fails with "no active transaction"
                } catch (\PDOException $pdoException) {
                    if ($pdoException->getMessage() !== 'There is no active transaction') {
                        // silent only this exception
                        throw $pdoException;
                    }
            }

            $this->afterTransactionRolledBack();

            throw $e;
        }
Originally created by @JarJak on GitHub (Jul 3, 2024). ### Bug Report I am not sure if this is bug for ORM or DBAL. Versions: PHP 8.2 ORM 2.19.5 DBAL 3.8.6 Symfony 8.2 Postgres 13.7 DBAL config: ``` 'connections' => [ 'default' => [ 'url' => '%env(resolve:DATABASE_URL)%', 'use_savepoints' => true, 'driver' => 'pdo_pgsql', ], ], ``` #### Summary When using transactions inside code, when exception occurs "entitymanager is closed" and transaction is rollbacked, that results in "PDOException: There is no active transaction" error. I have seen similar bugs reported, but they either happen with MySQL/MariaDB or in migrations. For me this happens with Postgres and in regular app code. Even though before rollbacking, Doctrine checks if it has a flag for active transaction before sending `ROLLBACK` sql to the database, for some reason this does not always work. Code fragment from UoW commit() method (which is always called in flush() regardless of transaction mode): https://github.com/doctrine/orm/blob/3.2.x/src/UnitOfWork.php#L439 ```php } catch (Throwable $e) { // exception "entitymanager is closed" caught $this->em->close(); // closes em (but is already closed) if ($conn->isTransactionActive()) { // this for some reason returns true $conn->rollBack(); // this fails with "no active transaction" } $this->afterTransactionRolledBack(); throw $e; } ``` #### Proposed solution One "dirty and hacky" way to fix it would be to add another try/catch inside the code above: ```php } catch (Throwable $e) { // exception "entitymanager is closed" caught $this->em->close(); // closes em (but is already closed) if ($conn->isTransactionActive()) { // this for some reason returns true try { $conn->rollBack(); // this fails with "no active transaction" } catch (\PDOException $pdoException) { if ($pdoException->getMessage() !== 'There is no active transaction') { // silent only this exception throw $pdoException; } } $this->afterTransactionRolledBack(); throw $e; } ```
admin closed this issue 2026-01-22 15:51:11 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#7395