doctrine/orm · error · LengthException

Unexpected number of database columns.

Error message

Unexpected number of database columns.

What it means

JoinedSubclassPersister::fetchVersionAndNotUpsertableValues() combines the expected generated/version column keys with the columns returned by the re-select across the joined inheritance tables. If the combine comes back empty, the collected column list and the query result disagree — an internal mapping invariant break, typically caused by a stale or hand-built ClassMetadata (versionField or generated attribute not backed by a real field mapping).

Source

Thrown at src/Persisters/Entity/JoinedSubclassPersister.php:568

            . ' FROM ' . $tableName . ' ' . $baseTableAlias
            . $joinSql
            . ' WHERE ' . implode(' = ? AND ', $identifier) . ' = ?';

        $flatId = $this->identifierFlattener->flattenIdentifier($versionedClass, $id);
        $values = $this->conn->fetchNumeric(
            $sql,
            array_values($flatId),
            $this->extractIdentifierTypes($id, $versionedClass),
        );

        if ($values === false) {
            throw new LengthException('Unexpected empty result for database query.');
        }

        $values = array_combine(array_keys($columnNames), $values);

        if (! $values) {
            throw new LengthException('Unexpected number of database columns.');
        }

        return $values;
    }

    private function getJoinSql(string $baseTableAlias): string
    {
        $joinSql          = '';
        $identifierColumn = $this->class->getIdentifierColumnNames();

        // INNER JOIN parent tables
        foreach ($this->class->parentClasses as $parentClassName) {
            $conditions  = [];
            $parentClass = $this->em->getClassMetadata($parentClassName);
            $tableAlias  = $this->getSQLTableAlias($parentClassName);
            $joinSql    .= ' INNER JOIN ' . $this->quoteStrategy->getTableName($parentClass, $this->platform) . ' ' . $tableAlias . ' ON ';

            foreach ($identifierColumn as $idColumn) {

View on GitHub (pinned to d9b9ff7301)

Solutions

  1. Confirm the #[Version] and `generated` fields exist as real mapped columns in the entity (and parent classes)
  2. Clear the metadata cache after schema/mapping changes
  3. Log the SELECT built by fetchVersionAndNotUpsertableValues and compare with the class-field mapping
Defensive patterns

Strategy: validation

Validate before calling

$meta = $em->getClassMetadata($childEntity::class);
foreach ([$meta, ...array_map(fn($p) => $em->getClassMetadata($p), $meta->parentClasses)] as $m) {
    if ($m->isVersioned && ! isset($m->fieldMappings[$m->versionField])) { throw new RuntimeException('Broken version metadata: ' . $m->name); }
}

Prevention

When it happens

Trigger: Joined-inheritance entity marked versioned or carrying generated columns whose metadata drifts from the actual field mappings; cached metadata from before a rename of a versioned/generated field.

Common situations: Renaming version or generated fields without clearing metadata cache; programmatically assembled ClassMetadata for inheritance hierarchies.

Related errors


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