{"record":{"id":"af9e0c4120e48a5d","repo":"doctrine/orm","slug":"unexpected-empty-result-for-database-query-af9e0c","errorCode":null,"errorMessage":"Unexpected empty result for database query.","messagePattern":"Unexpected empty result for database query\\.","errorType":"exception","errorClass":"LengthException","httpStatus":null,"severity":"error","filePath":"src/Persisters/Entity/JoinedSubclassPersister.php","lineNumber":562,"sourceCode":"        $identifier     = $this->quoteStrategy->getIdentifierColumnNames($versionedClass, $this->platform);\n        foreach ($identifier as $i => $idValue) {\n            $identifier[$i] = $baseTableAlias . '.' . $idValue;\n        }\n\n        $sql = 'SELECT ' . implode(', ', $columnNames)\n            . ' FROM ' . $tableName . ' ' . $baseTableAlias\n            . $joinSql\n            . ' WHERE ' . implode(' = ? AND ', $identifier) . ' = ?';\n\n        $flatId = $this->identifierFlattener->flattenIdentifier($versionedClass, $id);\n        $values = $this->conn->fetchNumeric(\n            $sql,\n            array_values($flatId),\n            $this->extractIdentifierTypes($id, $versionedClass),\n        );\n\n        if ($values === false) {\n            throw new LengthException('Unexpected empty result for database query.');\n        }\n\n        $values = array_combine(array_keys($columnNames), $values);\n\n        if (! $values) {\n            throw new LengthException('Unexpected number of database columns.');\n        }\n\n        return $values;\n    }\n\n    private function getJoinSql(string $baseTableAlias): string\n    {\n        $joinSql          = '';\n        $identifierColumn = $this->class->getIdentifierColumnNames();\n\n        // INNER JOIN parent tables\n        foreach ($this->class->parentClasses as $parentClassName) {","sourceCodeStart":544,"sourceCodeEnd":580,"githubUrl":"https://github.com/doctrine/orm/blob/d9b9ff73016bf598ae07515f97289ce8074e97a5/src/Persisters/Entity/JoinedSubclassPersister.php#L544-L580","documentation":"JoinedSubclassPersister (entity with joined-table inheritance) re-SELECTs version/generated columns after a write, joining the base and parent tables, filtered by the flattened identifier. fetchNumeric() returning false means the just-written row is no longer visible, so the invariant is broken and a LengthException is thrown mid-flush.","triggerScenarios":"flush() on a joined-inheritance entity with #[Version] or generated columns where the row disappears between write and re-select: AFTER INSERT/UPDATE triggers, concurrent deletes, row-level security, or connection routing that sends the re-select to a lagging replica.","commonSituations":"Audit/soft-delete triggers on child tables in inheritance hierarchies; tenant isolation policies; replica-routing connection wrappers; integration tests with READ UNCOMMITTED or nested transaction quirks.","solutions":["Inspect triggers and row-level security on ALL tables of the inheritance hierarchy","Guarantee write and re-select share one connection and transaction","Check the discriminator/identifier mapping so the WHERE matches the actual row","If a concurrent delete is expected, serialize the operations (lock the row with a pessimistic lock or reorder application logic)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Ensure the write and re-select share the connection; refuse flushes on read-only/replica connections\nif (! $em->getConnection()->isTransactionActive() && $usesReplicaRouting) { /* pin to primary before flush */ }","typeGuard":null,"tryCatchPattern":"try { $em->flush(); } catch (LengthException $e) { if ($e->getMessage() === 'Unexpected empty result for database query.') { /* check triggers/RLS on all hierarchy tables */ } throw $e; }","preventionTips":["Review triggers and RLS on every table of a joined hierarchy","Pin flushes to the primary connection","Use pessimistic locking when concurrent deletes are possible"],"tags":["flush","joined-inheritance","optimistic-lock","database-consistency"],"backgroundTag":"row-vanished-after-write","analyzedSha":"d9b9ff73016bf598ae07515f97289ce8074e97a5","analyzedAt":"2026-08-21T06:13:15.863Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}