doctrine/orm · error · RuntimeException

Could not resolve type of column "%s" of class "%s"

Error message

Could not resolve type of column "%s" of class "%s"

What it means

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.

Source

Thrown at src/Utility/PersisterHelper.php:127

        }

        // iterate over to-many association mappings
        foreach ($class->associationMappings as $assoc) {
            if (! $assoc->isManyToManyOwningSide()) {
                continue;
            }

            foreach ($assoc->joinTable->joinColumns as $joinColumn) {
                if ($joinColumn->name === $columnName) {
                    $targetColumnName = $joinColumn->referencedColumnName;
                    $targetClass      = $em->getClassMetadata($assoc->targetEntity);

                    return self::getTypeOfColumn($targetColumnName, $targetClass, $em);
                }
            }
        }

        throw new RuntimeException(sprintf(
            'Could not resolve type of column "%s" of class "%s"',
            $columnName,
            $class->getName(),
        ));
    }

    /**
     * Infers field types to be used by parameter type casting.
     *
     * @return list<ParameterType|int|string>
     * @phpstan-return list<ParameterType::*|ArrayParameterType::*|string>
     *
     * @throws QueryException
     */
    public static function inferParameterTypes(
        string $field,
        mixed $value,
        ClassMetadata $class,

View on GitHub (pinned to d9b9ff7301)

Solutions

  1. 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.
  2. 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.
  3. For many-to-many, verify both joinColumns and inverseJoinColumns of the join table reference existing columns on their respective entities.
  4. After fixing mappings, clear metadata and query caches so the corrected mapping is re-parsed.

Example fix

// before
#[ManyToMany(targetEntity: Group::class)]
#[JoinTable(name: 'user_group')]
#[JoinColumn(name: 'user_uid', referencedColumnName: 'user_id')] // target User has no 'user_id' column
private Collection $groups;

// after
#[ManyToMany(targetEntity: Group::class)]
#[JoinTable(name: 'user_group')]
#[JoinColumn(name: 'user_uid', referencedColumnName: 'id')] // matches User's id column
private Collection $groups;
Defensive patterns

Strategy: validation

Validate before calling

// At boot/build time, verify every join column reference resolves on its target class
foreach ($metadataFactory->getAllMetadata() as $class) {
    foreach ($class->getAssociationMappings() as $fieldName => $assoc) {
        $target = $em->getClassMetadata($assoc['targetEntity'] ?? $assoc->targetEntity);
        $joinColumns = isset($assoc['joinColumns']) ? $assoc['joinColumns'] : ($assoc->isManyToManyOwningSide() ? $assoc->joinTable->joinColumns : $assoc->joinColumns);
        foreach ($joinColumns as $jc) {
            $refName = $jc['referencedColumnName'] ?? $jc->referencedColumnName;
            if (! isset($target->fieldNames[$refName])) {
                throw new InvalidArgumentException(sprintf(
                    '%s::%s references unknown column %s on %s',
                    $class->getName(), $fieldName, $refName, $target->getName()
                ));
            }
        }
    }
}

Prevention

When it happens

Trigger: 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).

Common situations: #[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.

Related errors


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