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

  1. Pass an ORM ClassMetadata: new ClassMetadata($className), or fetch one from the EntityManager's metadata factory.
  2. Type-hint your calling code against Doctrine\ORM\Mapping\ClassMetadata so the mismatch is caught statically by PHPStan/IDE.
  3. 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

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


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