{"record":{"id":"f1e7624c56cd4b70","repo":"doctrine/orm","slug":"selecting-a-collection-by-index-is-only-supported-f1e762","errorCode":null,"errorMessage":"Selecting a collection by index is only supported on indexed collections.","messagePattern":"Selecting a collection by index is only supported on indexed collections\\.","errorType":"exception","errorClass":"BadMethodCallException","httpStatus":null,"severity":"error","filePath":"src/Persisters/Collection/OneToManyPersister.php","lineNumber":66,"sourceCode":"        $targetClass->isInheritanceTypeJoined()\n            ? $this->deleteJoinedEntityCollection($collection)\n            : $this->deleteEntityCollection($collection);\n    }\n\n    public function update(PersistentCollection $collection): void\n    {\n        // This can never happen. One to many can only be inverse side.\n        // For owning side one to many, it is required to have a join table,\n        // then classifying it as a ManyToManyPersister.\n        return;\n    }\n\n    public function get(PersistentCollection $collection, mixed $index): object|null\n    {\n        $mapping = $this->getMapping($collection);\n\n        if (! $mapping->isIndexed()) {\n            throw new BadMethodCallException('Selecting a collection by index is only supported on indexed collections.');\n        }\n\n        $persister = $this->uow->getEntityPersister($mapping->targetEntity);\n\n        return $persister->load(\n            [\n                $mapping->mappedBy  => $collection->getOwner(),\n                $mapping->indexBy() => $index,\n            ],\n            null,\n            $mapping,\n            [],\n            null,\n            1,\n        );\n    }\n\n    public function count(PersistentCollection $collection): int","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/doctrine/orm/blob/d9b9ff73016bf598ae07515f97289ce8074e97a5/src/Persisters/Collection/OneToManyPersister.php#L48-L84","documentation":"OneToManyPersister::get() loads one element of an EXTRA_LAZY one-to-many collection by key, requiring the mapping's indexBy field to build the criteria (mappedBy = owner AND indexBy = index). With no indexBy declared, it throws BadMethodCallException instead of running an unkeyed query. Reached via PersistentCollection::get()/offsetGet() only when the collection is uninitialized and fetch is EXTRA_LAZY.","triggerScenarios":"$children->get($key) / $children[$key] on an uninitialized EXTRA_LAZY #[OneToMany] association without `indexBy`.","commonSituations":"Optimizing large child collections with EXTRA_LAZY and then doing positional/keyed reads; assuming Doctrine keys collections by primary key automatically.","solutions":["Declare indexBy: #[OneToMany(targetEntity: Comment::class, mappedBy: 'post', indexBy: 'id')]","Initialize the collection before keyed access ($collection->initialize() or iterate it once)","Use a repository query instead of key access for single-element lookups"],"exampleFix":"// before\n#[OneToMany(targetEntity: Comment::class, mappedBy: 'post'), Fetch(FetchMode::EXTRA_LAZY)]\nprivate Collection $comments;\n$c = $post->getComments()->get(7); // throws\n\n// after\n#[OneToMany(targetEntity: Comment::class, mappedBy: 'post', indexBy: 'id'), Fetch(FetchMode::EXTRA_LAZY)]\nprivate Collection $comments;","handlingStrategy":"validation","validationCode":"$mapping = $em->getClassMetadata($post::class)->getAssociationMapping('comments');\nif (! $mapping->isIndexed()) { $post->getComments()->initialize(); }\n$comment = $post->getComments()->get($key);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add indexBy to EXTRA_LAZY one-to-many collections","Prefer repository queries for single-child lookups","Initialize collections before positional access"],"tags":["collection","one-to-many","extra-lazy","indexby"],"backgroundTag":"unindexed-collection-access","analyzedSha":"d9b9ff73016bf598ae07515f97289ce8074e97a5","analyzedAt":"2026-08-21T06:13:15.863Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}