doctrine/orm · error · LogicException

Uninitialized result set mapping.

Error message

Uninitialized result set mapping.

What it means

LogicException thrown by AbstractQuery::toIterable() (src/AbstractQuery.php:864) when getResultSetMapping() returns null. A ResultSetMapping (RSM) tells the hydrator how to map SQL columns to entity/scalar aliases. Regular DQL Query objects build the RSM lazily by parsing the DQL; only queries whose RSM must be supplied manually can end up with a null one.

Source

Thrown at src/AbstractQuery.php:864

     * @phpstan-param string|AbstractQuery::HYDRATE_*|null    $hydrationMode
     *
     * @return iterable<mixed>
     */
    public function toIterable(
        ArrayCollection|array $parameters = [],
        string|int|null $hydrationMode = null,
    ): iterable {
        if ($hydrationMode !== null) {
            $this->setHydrationMode($hydrationMode);
        }

        if (count($parameters) !== 0) {
            $this->setParameters($parameters);
        }

        $rsm = $this->getResultSetMapping();
        if ($rsm === null) {
            throw new LogicException('Uninitialized result set mapping.');
        }

        $stmt = $this->_doExecute();

        return $this->em->newHydrator($this->hydrationMode)->toIterable($stmt, $rsm, $this->hints);
    }

    /**
     * Executes the query.
     *
     * @phpstan-param ArrayCollection<int, Parameter>|mixed[]|null $parameters
     * @phpstan-param string|AbstractQuery::HYDRATE_*|null         $hydrationMode
     */
    public function execute(
        ArrayCollection|array|null $parameters = null,
        string|int|null $hydrationMode = null,
    ): mixed {
        if ($this->cacheable && $this->isCacheEnabled()) {

View on GitHub (pinned to d9b9ff7301)

Solutions

  1. Build native queries via EntityManager::createNativeQuery($sql, $rsm) — it calls setResultSetMapping() for you.
  2. If you construct NativeQuery manually, call $query->setResultSetMapping($rsm) before toIterable(); build the RSM with ResultSetMappingBuilder->addEntityResult()/addScalarResult() or addRootEntityFromClassMetadata().
  3. Prefer a DQL query ($em->createQuery()) when possible — its RSM is derived from the DQL automatically.
  4. Audit custom AbstractQuery subclasses and make _doExecute() paths always leave a non-null RSM.

Example fix

// before
$query = new NativeQuery($em);
$query->setSql('SELECT id, email FROM user WHERE active = 1');
foreach ($query->toIterable() as $row) { ... } // LogicException: Uninitialized result set mapping.

// after
$rsm = new ResultSetMappingBuilder($em);
$rsm->addRootEntityFromClassMetadata(User::class, 'u');
$query = $em->createNativeQuery('SELECT id, email FROM user WHERE active = 1', $rsm);
foreach ($query->toIterable() as $user) { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Only route queries with a known ResultSetMapping into toIterable()
if ($query instanceof \Doctrine\ORM\NativeQuery && ! $query->getSQL()) {
    throw new LogicException('Native query lacks SQL/RSM setup');
}
// Build via the EM so the RSM is always attached:
$query = $em->createNativeQuery($sql, $rsm);

Try / catch

try {
    foreach ($query->toIterable() as $row) { /* ... */ }
} catch (\LogicException $e) {
    // misconfiguration at build time: fail fast with the query class/name in context
}

Prevention

When it happens

Trigger: Calling toIterable() on a NativeQuery (or a custom AbstractQuery subclass) that never had setResultSetMapping() called — typically a NativeQuery constructed with `new NativeQuery($em)` instead of EntityManager::createNativeQuery($sql, $rsm), or a hand-rolled AbstractQuery subclass whose _doExecute() returns a statement without an RSM.

Common situations: Migrating streaming/batch-processing code from getResult() to toIterable(); refactoring away from EntityManager::createNativeQuery() and losing the second constructor argument; custom query classes from internal frameworks that predate the RSM contract.

Related errors


AI-assisted analysis of doctrine/orm@d9b9ff7301 (2026-08-21). Data as JSON: /api/errors/0cf19607af7afbc2. Report an issue: GitHub.