{"record":{"id":"916c80db8a236051","repo":"doctrine/orm","slug":"could-not-resolve-type-of-column-s-of-class-s","errorCode":null,"errorMessage":"Could not resolve type of column \"%s\" of class \"%s\"","messagePattern":"Could not resolve type of column \"(.+?)\" of class \"(.+?)\"","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Utility/PersisterHelper.php","lineNumber":127,"sourceCode":"        }\n\n        // iterate over to-many association mappings\n        foreach ($class->associationMappings as $assoc) {\n            if (! $assoc->isManyToManyOwningSide()) {\n                continue;\n            }\n\n            foreach ($assoc->joinTable->joinColumns as $joinColumn) {\n                if ($joinColumn->name === $columnName) {\n                    $targetColumnName = $joinColumn->referencedColumnName;\n                    $targetClass      = $em->getClassMetadata($assoc->targetEntity);\n\n                    return self::getTypeOfColumn($targetColumnName, $targetClass, $em);\n                }\n            }\n        }\n\n        throw new RuntimeException(sprintf(\n            'Could not resolve type of column \"%s\" of class \"%s\"',\n            $columnName,\n            $class->getName(),\n        ));\n    }\n\n    /**\n     * Infers field types to be used by parameter type casting.\n     *\n     * @return list<ParameterType|int|string>\n     * @phpstan-return list<ParameterType::*|ArrayParameterType::*|string>\n     *\n     * @throws QueryException\n     */\n    public static function inferParameterTypes(\n        string $field,\n        mixed $value,\n        ClassMetadata $class,","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/doctrine/orm/blob/d9b9ff73016bf598ae07515f97289ce8074e97a5/src/Utility/PersisterHelper.php#L109-L145","documentation":"PersisterHelper::getTypeOfColumn() maps a database column name to its Doctrine type by checking the class's field mappings, then to-one association join columns, then many-to-many join-table columns (following referencedColumnName into the target class recursively). If no mapping references the given column name, type resolution is impossible and it throws - almost always a mapping inconsistency where a referencedColumnName or column name does not exist on the referenced class.","triggerScenarios":"Any code path that must type-cast identifiers or parameters by column: Criteria filtering on a to-many collection (OneToManyPersister/ManyToManyPersister), JOIN ... WITH / IDENTITY() handling in SqlWalker, ResultSetMappingBuilder, pagination walkers, and multi-table UPDATE/DELETE executors - all call getTypeOfColumn with a join column's referencedColumnName that does not match any column on the target entity (typo, custom id column name, referenced field not mapped).","commonSituations":"#[JoinColumn(referencedColumnName: 'user_id')] pointing at a name that is neither the target's id column nor any mapped field; target entities with custom id column names; referenced column living on a subclass in inheritance scenarios; stale metadata cache after a column rename on the target entity.","solutions":["Fix the JoinColumn mapping so referencedColumnName matches an actual column on the target entity (usually its primary key, e.g. 'id'), or omit referencedColumnName to use the target's id by default.","If you reference a non-id unique column, make sure that column is mapped as a field on the target entity with the exact same name.","For many-to-many, verify both joinColumns and inverseJoinColumns of the join table reference existing columns on their respective entities.","After fixing mappings, clear metadata and query caches so the corrected mapping is re-parsed."],"exampleFix":"// before\n#[ManyToMany(targetEntity: Group::class)]\n#[JoinTable(name: 'user_group')]\n#[JoinColumn(name: 'user_uid', referencedColumnName: 'user_id')] // target User has no 'user_id' column\nprivate Collection $groups;\n\n// after\n#[ManyToMany(targetEntity: Group::class)]\n#[JoinTable(name: 'user_group')]\n#[JoinColumn(name: 'user_uid', referencedColumnName: 'id')] // matches User's id column\nprivate Collection $groups;","handlingStrategy":"validation","validationCode":"// At boot/build time, verify every join column reference resolves on its target class\nforeach ($metadataFactory->getAllMetadata() as $class) {\n    foreach ($class->getAssociationMappings() as $fieldName => $assoc) {\n        $target = $em->getClassMetadata($assoc['targetEntity'] ?? $assoc->targetEntity);\n        $joinColumns = isset($assoc['joinColumns']) ? $assoc['joinColumns'] : ($assoc->isManyToManyOwningSide() ? $assoc->joinTable->joinColumns : $assoc->joinColumns);\n        foreach ($joinColumns as $jc) {\n            $refName = $jc['referencedColumnName'] ?? $jc->referencedColumnName;\n            if (! isset($target->fieldNames[$refName])) {\n                throw new InvalidArgumentException(sprintf(\n                    '%s::%s references unknown column %s on %s',\n                    $class->getName(), $fieldName, $refName, $target->getName()\n                ));\n            }\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Let referencedColumnName default to the target's primary key instead of naming it manually","After renaming id columns, update every #[JoinColumn(referencedColumnName: ...)] that points at them","Run doctrine:schema:validate plus a mapping sanity check in CI; clear metadata cache after mapping edits"],"tags":["doctrine-orm","mapping","join-column","referenced-column-name","persister-helper","criteria","many-to-many"],"backgroundTag":"orm-mapping-join-column-mismatch","analyzedSha":"d9b9ff73016bf598ae07515f97289ce8074e97a5","analyzedAt":"2026-08-21T06:13:15.863Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}