{"record":{"id":"6e925a6353bface7","repo":"doctrine/orm","slug":"filtering-a-collection-by-criteria-is-not-supporte","errorCode":null,"errorMessage":"Filtering a collection by Criteria is not supported by this CollectionPersister.","messagePattern":"Filtering a collection by Criteria is not supported by this CollectionPersister\\.","errorType":"exception","errorClass":"BadMethodCallException","httpStatus":null,"severity":"error","filePath":"src/Persisters/Collection/OneToManyPersister.php","lineNumber":151,"sourceCode":"        }\n\n        $mapping   = $this->getMapping($collection);\n        $persister = $this->uow->getEntityPersister($mapping->targetEntity);\n\n        // only works with single id identifier entities. Will throw an\n        // exception in Entity Persisters if that is not the case for the\n        // 'mappedBy' field.\n        $criteria = Criteria::create(true)->where(Criteria::expr()->eq($mapping->mappedBy, $collection->getOwner()));\n\n        return $persister->exists($element, $criteria);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function loadCriteria(PersistentCollection $collection, Criteria $criteria): array\n    {\n        throw new BadMethodCallException('Filtering a collection by Criteria is not supported by this CollectionPersister.');\n    }\n\n    /**\n     * @throws DBALException\n     * @throws EntityNotFoundException\n     * @throws MappingException\n     */\n    private function deleteEntityCollection(PersistentCollection $collection): int\n    {\n        $mapping     = $this->getMapping($collection);\n        $identifier  = $this->uow->getEntityIdentifier($collection->getOwner());\n        $sourceClass = $this->em->getClassMetadata($mapping->sourceEntity);\n        $targetClass = $this->em->getClassMetadata($mapping->targetEntity);\n        $columns     = [];\n        $parameters  = [];\n        $types       = [];\n\n        foreach ($this->em->getMetadataFactory()->getOwningSide($mapping)->joinColumns as $joinColumn) {","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/doctrine/orm/blob/d9b9ff73016bf598ae07515f97289ce8074e97a5/src/Persisters/Collection/OneToManyPersister.php#L133-L169","documentation":"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.","triggerScenarios":"$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.","commonSituations":"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.","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')..."],"exampleFix":"// before\n#[OneToMany(targetEntity: Task::class, mappedBy: 'project'), Fetch(FetchMode::EXTRA_LAZY)]\nprivate Collection $tasks;\n$open = $project->getTasks()->matching(Criteria::create()->where(Criteria::expr()->eq('done', false))); // throws\n\n// after\n$project->getTasks()->initialize();\n$open = $project->getTasks()->matching(Criteria::create()->where(Criteria::expr()->eq('done', false)));","handlingStrategy":"fallback","validationCode":"$collection = $project->getTasks();\nif (! $collection->isInitialized()) {\n    $collection->initialize(); // in-memory matching() works from here\n}\n$open = $collection->matching($criteria);","typeGuard":null,"tryCatchPattern":"try { $result = $collection->matching($criteria); } catch (BadMethodCallException) { $collection->initialize(); $result = $collection->matching($criteria); }","preventionTips":["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"],"tags":["collection","one-to-many","criteria","matching","extra-lazy"],"backgroundTag":"unsupported-collection-operation","analyzedSha":"d9b9ff73016bf598ae07515f97289ce8074e97a5","analyzedAt":"2026-08-21T06:13:15.863Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}