{"record":{"id":"b18e069ed4e0aef8","repo":"doctrine/orm","slug":"unexpected-number-of-database-columns-b18e06","errorCode":null,"errorMessage":"Unexpected number of database columns.","messagePattern":"Unexpected number of database columns\\.","errorType":"exception","errorClass":"LengthException","httpStatus":null,"severity":"error","filePath":"src/Persisters/Entity/JoinedSubclassPersister.php","lineNumber":568,"sourceCode":"            . ' 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) {\n            $conditions  = [];\n            $parentClass = $this->em->getClassMetadata($parentClassName);\n            $tableAlias  = $this->getSQLTableAlias($parentClassName);\n            $joinSql    .= ' INNER JOIN ' . $this->quoteStrategy->getTableName($parentClass, $this->platform) . ' ' . $tableAlias . ' ON ';\n\n            foreach ($identifierColumn as $idColumn) {","sourceCodeStart":550,"sourceCodeEnd":586,"githubUrl":"https://github.com/doctrine/orm/blob/d9b9ff73016bf598ae07515f97289ce8074e97a5/src/Persisters/Entity/JoinedSubclassPersister.php#L550-L586","documentation":"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).","triggerScenarios":"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.","commonSituations":"Renaming version or generated fields without clearing metadata cache; programmatically assembled ClassMetadata for inheritance hierarchies.","solutions":["Confirm the #[Version] and `generated` fields exist as real mapped columns in the entity (and parent classes)","Clear the metadata cache after schema/mapping changes","Log the SELECT built by fetchVersionAndNotUpsertableValues and compare with the class-field mapping"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"$meta = $em->getClassMetadata($childEntity::class);\nforeach ([$meta, ...array_map(fn($p) => $em->getClassMetadata($p), $meta->parentClasses)] as $m) {\n    if ($m->isVersioned && ! isset($m->fieldMappings[$m->versionField])) { throw new RuntimeException('Broken version metadata: ' . $m->name); }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clear metadata cache after inheritance-hierarchy mapping changes","Keep #[Version] on one real column of the declaring class","Run doctrine:schema:validate after mapping edits"],"tags":["orm-internal","joined-inheritance","version-field","metadata-cache"],"backgroundTag":"orm-metadata-inconsistency","analyzedSha":"d9b9ff73016bf598ae07515f97289ce8074e97a5","analyzedAt":"2026-08-21T06:13:15.863Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}