doctrine/orm · error · BadMethodCallException
Filtering a collection by Criteria is not supported by this
Error message
Filtering a collection by Criteria is not supported by this CollectionPersister.
What it means
PersistentCollection::matching($criteria) on a non-initialized collection delegates to the collection persister's loadCriteria(). ManyToManyPersister implements it (filtering over the join table), but OneToManyPersister::loadCriteria() is a stub that always throws BadMethodCallException — filtering an EXTRA_LAZY one-to-many collection by Criteria is simply not implemented.
Source
Thrown at src/Persisters/Collection/OneToManyPersister.php:151
}
$mapping = $this->getMapping($collection);
$persister = $this->uow->getEntityPersister($mapping->targetEntity);
// only works with single id identifier entities. Will throw an
// exception in Entity Persisters if that is not the case for the
// 'mappedBy' field.
$criteria = Criteria::create(true)->where(Criteria::expr()->eq($mapping->mappedBy, $collection->getOwner()));
return $persister->exists($element, $criteria);
}
/**
* {@inheritDoc}
*/
public function loadCriteria(PersistentCollection $collection, Criteria $criteria): array
{
throw new BadMethodCallException('Filtering a collection by Criteria is not supported by this CollectionPersister.');
}
/**
* @throws DBALException
* @throws EntityNotFoundException
* @throws MappingException
*/
private function deleteEntityCollection(PersistentCollection $collection): int
{
$mapping = $this->getMapping($collection);
$identifier = $this->uow->getEntityIdentifier($collection->getOwner());
$sourceClass = $this->em->getClassMetadata($mapping->sourceEntity);
$targetClass = $this->em->getClassMetadata($mapping->targetEntity);
$columns = [];
$parameters = [];
$types = [];
foreach ($this->em->getMetadataFactory()->getOwningSide($mapping)->joinColumns as $joinColumn) {View on GitHub (pinned to d9b9ff7301)
Solutions
- Remove FetchMode::EXTRA_LAZY from that one-to-many association so matching() initializes and filters in memory
- Initialize explicitly before matching: $collection->initialize(); $collection->matching($criteria)
- Replace matching() with a repository query: $repo->createQueryBuilder('c')->where('c.parent = :p')...
Example fix
// before
#[OneToMany(targetEntity: Task::class, mappedBy: 'project'), Fetch(FetchMode::EXTRA_LAZY)]
private Collection $tasks;
$open = $project->getTasks()->matching(Criteria::create()->where(Criteria::expr()->eq('done', false))); // throws
// after
$project->getTasks()->initialize();
$open = $project->getTasks()->matching(Criteria::create()->where(Criteria::expr()->eq('done', false))); Defensive patterns
Strategy: fallback
Validate before calling
$collection = $project->getTasks();
if (! $collection->isInitialized()) {
$collection->initialize(); // in-memory matching() works from here
}
$open = $collection->matching($criteria); Try / catch
try { $result = $collection->matching($criteria); } catch (BadMethodCallException) { $collection->initialize(); $result = $collection->matching($criteria); } Prevention
- Do not combine EXTRA_LAZY one-to-many with matching()
- Wrap collection filtering in a repository method that queries by mappedBy
- Initialize collections before Criteria filtering when in doubt
When it happens
Trigger: $entity->getChildren()->matching(Criteria::create()->where(...)) where getChildren() is an uninitialized one-to-many collection with fetch: EXTRA_LAZY. With default LAZY fetch, matching() initializes and filters in memory, so only EXTRA_LAZY hits the persister.
Common situations: Enabling EXTRA_LAZY on large child collections and then reusing existing matching() calls from when the collection was lazy; generic collection-filtering code that works on many-to-many but runs against one-to-many.
Related errors
- Selecting a collection by index is only supported on indexed
- This mapping is not indexed. Use %s::isIndexed() to check th
- Selecting a collection by index is only supported on indexed
- Unknown composite {type}
- <index-by /> is not a valid tag
AI-assisted analysis of doctrine/orm@d9b9ff7301 (2026-08-21).
Data as JSON: /api/errors/6e925a6353bface7.
Report an issue: GitHub.