doctrine/instantiator · error · Doctrine\Instantiator\Exception\InvalidArgumentException
The provided class "%s" is abstract, and cannot be instantia
Error message
The provided class "%s" is abstract, and cannot be instantiated
What it means
Thrown by fromAbstractClass() when getReflectionClass() (src/Instantiator.php:153-154) finds the requested class is abstract. Even though the instantiator bypasses constructors via ReflectionClass::newInstanceWithoutConstructor(), PHP forbids creating instances of abstract classes, so the library refuses up front. The message names the abstract class so you can redirect the call to a concrete subclass.
Source
Thrown at src/Exception/InvalidArgumentException.php:40
return new self(sprintf('The provided type "%s" is an interface, and cannot be instantiated', $className));
}
if (trait_exists($className)) {
return new self(sprintf('The provided type "%s" is a trait, and cannot be instantiated', $className));
}
return new self(sprintf('The provided class "%s" does not exist', $className));
}
/**
* @phpstan-param ReflectionClass<T> $reflectionClass
*
* @template T of object
*/
public static function fromAbstractClass(ReflectionClass $reflectionClass): self
{
return new self(sprintf(
'The provided class "%s" is abstract, and cannot be instantiated',
$reflectionClass->getName(),
));
}
public static function fromEnum(string $className): self
{
return new self(sprintf(
'The provided class "%s" is an enum, and cannot be instantiated',
$className,
));
}
}
View on GitHub (pinned to cbb879d6ee)
Solutions
- Instantiate a concrete subclass instead: pass UserRepository::class rather than AbstractRepository::class.
- If the abstract type comes from a container binding or config, fix the mapping so the concrete implementation name is resolved before calling instantiate().
- After a dependency upgrade, grep call sites for the newly abstract class name and update them to the concrete replacements.
Example fix
// before $repository = $instantiator->instantiate(AbstractRepository::class); // InvalidArgumentException: The provided class "AbstractRepository" is abstract, // and cannot be instantiated // after: ask for the concrete subclass $repository = $instantiator->instantiate(UserRepository::class);
Defensive patterns
Strategy: validation
Validate before calling
$reflection = new ReflectionClass($className);
if ($reflection->isAbstract()) {
throw new LogicException(sprintf('%s is abstract: pass a concrete subclass.', $className));
}
$object = (new Instantiator())->instantiate($className); Type guard
function isConcreteClass(string $className): bool
{
return class_exists($className)
&& ! (new ReflectionClass($className))->isAbstract();
} Try / catch
use Doctrine\Instantiator\Exception\InvalidArgumentException;
try {
$instance = $instantiator->instantiate($className);
} catch (InvalidArgumentException $e) {
if (str_contains($e->getMessage(), 'is abstract')) {
// resolve the abstract type to a mapped concrete implementation, then retry
$className = $this->container->getConcreteClass($className);
return $instantiator->instantiate($className);
}
throw $e;
} Prevention
- Make container bindings map abstract types to concrete implementations and resolve before instantiating.
- Filter metadata-driven type lists with ReflectionClass::isAbstract().
- After upgrading a dependency that made a base class abstract, grep call sites for the old name.
When it happens
Trigger: Calling (new Instantiator())->instantiate(AbstractController::class), AbstractRepository::class, or any abstract base FQCN. The ReflectionClass built at src/Instantiator.php:151 reports isAbstract() === true and fromAbstractClass($reflection) is thrown with the class name from $reflectionClass->getName().
Common situations: A factory or container resolves by abstract type name and forgot to map it to a concrete implementation; a base class was made abstract during a framework/library upgrade but call sites still reference it; fixture/prototype tooling receives 'base entity' names from metadata that lists parents instead of leaf classes.
Related errors
- The provided type "%s" is an interface, and cannot be instan
- The provided type "%s" is a trait, and cannot be instantiate
- The provided class "%s" is an enum, and cannot be instantiat
- The provided class "%s" does not exist
- An exception was raised while trying to instantiate an insta
AI-assisted analysis of doctrine/instantiator@cbb879d6ee (2026-08-21).
Data as JSON: /api/errors/07273f65f38140e8.
Report an issue: GitHub.