doctrine/orm · error · LogicException
This mapping is not indexed. Use %s::isIndexed() to check th
Error message
This mapping is not indexed. Use %s::isIndexed() to check that before calling %s.
What it means
To-many association mappings expose indexBy() to read the field that keys an indexed collection (the `indexBy` option of #[OneToMany]/#[ManyToMany]). The property is null unless the mapping declared it; isIndexed() exists exactly to guard access (it carries an @phpstan-assert-if-true). Calling indexBy() on a mapping without the option throws this LogicException.
Source
Thrown at src/Mapping/ToManyAssociationMappingImplementation.php:44
*/
public array $orderBy = [];
/** @return array<string, 'asc'|'desc'> */
final public function orderBy(): array
{
return $this->orderBy;
}
/** @phpstan-assert-if-true !null $this->indexBy */
final public function isIndexed(): bool
{
return $this->indexBy !== null;
}
final public function indexBy(): string
{
if (! $this->isIndexed()) {
throw new LogicException(sprintf(
'This mapping is not indexed. Use %s::isIndexed() to check that before calling %s.',
self::class,
__METHOD__,
));
}
return $this->indexBy;
}
/** @return list<string> */
public function __sleep(): array
{
$serialized = parent::__sleep();
if ($this->indexBy !== null) {
$serialized[] = 'indexBy';
}
View on GitHub (pinned to d9b9ff7301)
Solutions
- Add indexBy to the association mapping: #[ManyToMany(targetEntity: Tag::class, indexBy: 'slug')] or indexBy on #[OneToMany]
- Check $mapping->isIndexed() before calling indexBy()
- If indexing is not intended, iterate the collection instead of key access
Example fix
// before
#[ManyToMany(targetEntity: Tag::class)]
private Collection $tags;
$tag = $article->getTags()->get('php'); // throws
// after
#[ManyToMany(targetEntity: Tag::class, indexBy: 'slug')]
private Collection $tags;
$tag = $article->getTags()->get('php'); Defensive patterns
Strategy: validation
Validate before calling
$mapping = $em->getClassMetadata($owner::class)->getAssociationMapping($field);
if ($mapping->isIndexed()) { $key = $mapping->indexBy(); } Prevention
- Declare indexBy whenever code will key the collection
- Check isIndexed() before indexBy()
- Cover keyed collection access in tests with EXTRA_LAZY enabled
When it happens
Trigger: Calling $mapping->indexBy() directly without checking isIndexed(); indirectly via PersistentCollection::get()/offsetGet()/containsKey() on an EXTRA_LAZY collection whose mapping has no indexBy (the persisters call indexBy() to build the WHERE clause).
Common situations: Code assuming collections are keyed by a field ('id', 'slug') without declaring indexBy in the mapping; enabling fetch: EXTRA_LAZY and then doing $collection[$key] or isset($collection[$key]).
Related errors
- Selecting a collection by index is only supported on indexed
- Selecting a collection by index is only supported on indexed
- Filtering a collection by Criteria is not supported by this
- Attempting to change readonly property %s::$%s.
- ClassMetadata::setTable() has to be called before defining a
AI-assisted analysis of doctrine/orm@d9b9ff7301 (2026-08-21).
Data as JSON: /api/errors/6f620e913da228e9.
Report an issue: GitHub.