doctrine/orm · error · TypeError
Argument #2 passed to %s() must be an instance of %s, %s giv
Error message
Argument #2 passed to %s() must be an instance of %s, %s given.
What it means
DatabaseDriver (Doctrine's schema-to-entities reverse-engineering driver) implements the shared persistence MappingDriver interface, whose loadMetadataForClass() accepts any PersistenceClassMetadata. The ORM implementation requires Doctrine\ORM\Mapping\ClassMetadata specifically and throws a TypeError naming the method, the expected class and the actual type otherwise.
Source
Thrown at src/Mapping/Driver/DatabaseDriver.php:175
}
public function setInflector(Inflector $inflector): void
{
$this->inflector = $inflector;
}
/**
* {@inheritDoc}
*
* @param class-string<T> $className
* @param ClassMetadata<T> $metadata
*
* @template T of object
*/
public function loadMetadataForClass(string $className, PersistenceClassMetadata $metadata): void
{
if (! $metadata instanceof ClassMetadata) {
throw new TypeError(sprintf(
'Argument #2 passed to %s() must be an instance of %s, %s given.',
__METHOD__,
ClassMetadata::class,
get_debug_type($metadata),
));
}
$this->reverseEngineerMappingFromDatabase();
if (! isset($this->classToTableNames[$className])) {
throw new InvalidArgumentException('Unknown class ' . $className);
}
$tableName = $this->classToTableNames[$className];
$metadata->name = $className;
$metadata->table['name'] = $tableName;
View on GitHub (pinned to d9b9ff7301)
Solutions
- Pass an ORM ClassMetadata: new ClassMetadata($className), or fetch one from the EntityManager's metadata factory.
- Type-hint your calling code against Doctrine\ORM\Mapping\ClassMetadata so the mismatch is caught statically by PHPStan/IDE.
- If you need a driver usable with another persistence library, that library needs its own driver implementation — DatabaseDriver is ORM-only.
Example fix
// before use Doctrine\Persistence\Mapping\ClassMetadata as PersistenceClassMetadata; $driver->loadMetadataForClass($class, $odmMetadata); // TypeError // after use Doctrine\ORM\Mapping\ClassMetadata; $driver->loadMetadataForClass($class, new ClassMetadata($class));
Defensive patterns
Strategy: type-guard
Type guard
if (! $metadata instanceof \Doctrine\ORM\Mapping\ClassMetadata) {
throw new InvalidArgumentException('ORM DatabaseDriver requires ORM ClassMetadata, got ' . get_debug_type($metadata));
} Prevention
- Type-hint call sites with the ORM-specific ClassMetadata, not the persistence interface.
- Keep separate drivers per persistence library; do not share a DatabaseDriver across managers.
- Let PHPStan verify the generic template T of object binds to your entity class.
When it happens
Trigger: Calling $databaseDriver->loadMetadataForClass($className, $metadata) with a $metadata that is not Doctrine\ORM\Mapping\ClassMetadata — for example a ClassMetadata object from Doctrine ODM (MongoDB), Doctrine PHPCR, or a custom PersistenceClassMetadata implementation.
Common situations: Sharing drivers or metadata factories between persistence libraries (ORM + ODM in one project, common in Symfony with multiple doctrine connections/managers); custom tooling typed against the shared persistence interface instead of the ORM class.
Related errors
- Unknown class {className}
- Table {tableName} has no primary key. Doctrine does not supp
- Uninitialized result set mapping.
- Unable to use access strategy type of [%s] without a Concurr
- Unrecognized access strategy type [%s]
AI-assisted analysis of doctrine/orm@d9b9ff7301 (2026-08-21).
Data as JSON: /api/errors/309e0d90b1fbff0a.
Report an issue: GitHub.