Misleading ORMInvalidArgumentException after removal of referred entity of ManyToOne association with onDelete: 'CASCADE' #7393

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

Originally created by @tobiasgv on GitHub (Jul 2, 2024).

Bug Report

Q A
BC Break no
Version 3.2.1

Summary

For a ManyToOne association where the owning side (class A) has the onDelete: 'CASCADE' option set: when a referred entity (of class B) is removed by the entity manager then a subsequent call to persist()+flush() causes a misleading ORMInvalidArgumentException:

Doctrine\ORM\ORMInvalidArgumentException: A new entity was found through the relationship 'A#b' that was not configured to cascade persist operations for entity: XXX. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).

for managed entities of class A (which were cascade deleted by the DB), since the referenced entity of class B is mis-interpreted as a new entity.

How to reproduce


        #[ORM\JoinColumn(name: 'b_identifier', referencedColumnName: 'identifier', onDelete: 'CASCADE')]
        #[ORM\ManyToOne(targetEntity: B::class)]
        private ?B $b = null;

        $b = new B();
        $this->entityManger->persist($b);
        $this->entityManger->flush();

        $a = new A();
        $a->setB($b);
        $this->entityManger->persist($a);
        $this->entityManger->flush();

        $this->entityManger->remove($b);
        $this->entityManger->flush();

        $b2 = new B();
        $this->entityManger->persist($b2);
        $this->entityManger->flush(); // throws

Expected behavior

No exception should be thrown.

Workaround

Unsetting the referenced entity before flushing prevents the exception:
$a->setB(null);

Originally created by @tobiasgv on GitHub (Jul 2, 2024). ### Bug Report | Q | A |------------ | ------ | BC Break | no | Version | 3.2.1 #### Summary For a ManyToOne association where the owning side (class A) has the onDelete: 'CASCADE' option set: when a referred entity (of class B) is removed by the entity manager then a subsequent call to persist()+flush() causes a misleading ORMInvalidArgumentException: `Doctrine\ORM\ORMInvalidArgumentException: A new entity was found through the relationship 'A#b' that was not configured to cascade persist operations for entity: XXX. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). ` for managed entities of class A (which were cascade deleted by the DB), since the referenced entity of class B is mis-interpreted as a new entity. #### How to reproduce ``` #[ORM\JoinColumn(name: 'b_identifier', referencedColumnName: 'identifier', onDelete: 'CASCADE')] #[ORM\ManyToOne(targetEntity: B::class)] private ?B $b = null; ``` ``` $b = new B(); $this->entityManger->persist($b); $this->entityManger->flush(); $a = new A(); $a->setB($b); $this->entityManger->persist($a); $this->entityManger->flush(); $this->entityManger->remove($b); $this->entityManger->flush(); $b2 = new B(); $this->entityManger->persist($b2); $this->entityManger->flush(); // throws ``` #### Expected behavior No exception should be thrown. #### Workaround Unsetting the referenced entity before flushing prevents the exception: ` $a->setB(null); `
Author
Owner

@stof commented on GitHub (Jul 4, 2024):

The issue in your case is that $a still reference $b in your UnitOfWork.

onDelete: 'CASCADE' is about configuring the database-level cascading on the foreign key. This will lead to the row being deleted from the database in the a table, but the ORM still has $a in its UnitOfWork as it does not know about this removal.

If your schema relies on onDelete: 'CASCADE' (or onDelete: 'SET NULL'), you should be careful when you keep using the UnitOfWork after a flush. To be reliable, you would have to clear the UnitOfWork after a flush involving removals (as such flushes might have triggered an onDelete behavior)

@stof commented on GitHub (Jul 4, 2024): The issue in your case is that `$a` still reference `$b` in your UnitOfWork. `onDelete: 'CASCADE'` is about configuring the database-level cascading on the foreign key. This will lead to the row being deleted from the database in the `a` table, but the ORM still has `$a` in its UnitOfWork as it does not know about this removal. If your schema relies on `onDelete: 'CASCADE'` (or `onDelete: 'SET NULL'`), you should be careful when you keep using the UnitOfWork after a flush. To be reliable, you would have to clear the UnitOfWork after a flush involving removals (as such flushes might have triggered an `onDelete` behavior)
Author
Owner

@tobiasgv commented on GitHub (Jul 8, 2024):

Ok, thank you. I will clear the UnitOfWork after the removal.

@tobiasgv commented on GitHub (Jul 8, 2024): Ok, thank you. I will clear the UnitOfWork after the removal.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#7393