doctrine/instantiator · error · Doctrine\Instantiator\Exception\InvalidArgumentException
The provided type "%s" is an interface, and cannot be instan
Error message
The provided type "%s" is an interface, and cannot be instantiated
What it means
doctrine/instantiator creates objects without invoking their constructors. Its internal getReflectionClass() gate (src/Instantiator.php:143) requires class_exists() to return true; interfaces never satisfy that, so fromNonExistingClass() runs and detects via interface_exists() that the given name is an interface. The error means the string passed to Instantiator::instantiate() names an interface type, which can never be instantiated directly in PHP.
Source
Thrown at src/Exception/InvalidArgumentException.php:22
namespace Doctrine\Instantiator\Exception;
use InvalidArgumentException as BaseInvalidArgumentException;
use ReflectionClass;
use function interface_exists;
use function sprintf;
use function trait_exists;
/**
* Exception for invalid arguments provided to the instantiator
*/
class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface
{
public static function fromNonExistingClass(string $className): self
{
if (interface_exists($className)) {
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',View on GitHub (pinned to cbb879d6ee)
Solutions
- Resolve the interface to a concrete implementing class before calling instantiate(), e.g. look up the container binding and pass FileLogger::class instead of LoggerInterface::class.
- If the class name comes from configuration, fix the mapping entry so it points to the concrete class.
- If you iterate lists of type names, filter them first: keep only names where class_exists($name) is true (interfaces and traits fail this check automatically).
Example fix
// before $logger = (new Instantiator())->instantiate(LoggerInterface::class); // InvalidArgumentException: The provided type "LoggerInterface" is an interface, // and cannot be instantiated // after: pass the concrete implementation, not the abstraction $logger = (new Instantiator())->instantiate(FileLogger::class);
Defensive patterns
Strategy: validation
Validate before calling
use function interface_exists;
if (interface_exists($className)) {
throw new LogicException(
sprintf('%s is an interface: resolve a concrete implementation before instantiating.', $className)
);
}
$object = (new Instantiator())->instantiate($className); Type guard
/** @phpstan-assert-if-true !interface-string $className */
function isInstantiableClassName(string $className): bool
{
return class_exists($className) && ! interface_exists($className, false);
} Try / catch
use Doctrine\Instantiator\Exception\InvalidArgumentException;
try {
$instance = $instantiator->instantiate($className);
} catch (InvalidArgumentException $e) {
// bad input: interface/trait/missing/abstract/enum name — surface it at the config boundary
throw new InvalidTypeConfiguration($e->getMessage(), 0, $e);
} Prevention
- Always resolve container bindings to concrete class names before calling instantiate().
- Filter type lists with class_exists($name) — it is false for interfaces and traits automatically.
- Prefer ClassName::class constants over hand-written strings so static analysis can verify types.
When it happens
Trigger: Calling (new Instantiator())->instantiate($className) where $className is an interface FQCN, e.g. Psr\Log\LoggerInterface::class or Doctrine\Instantiator\InstantiatorInterface::class. class_exists() returns false for interfaces, control enters fromNonExistingClass(), interface_exists($className) is true, and the interface message variant is returned. Typical caller code: DI containers, fixture/proxy factories, or test libraries that feed a type map straight into instantiate().
Common situations: A service container or config file maps an identifier to an interface instead of a concrete implementation; generic factory code iterates 'all types' (classes, interfaces, traits) from reflection or a manifest and passes each to instantiate(); a variable that was supposed to hold the resolved implementation still holds the abstraction name after a refactor.
Related errors
- The provided type "%s" is a trait, and cannot be instantiate
- The provided class "%s" is abstract, and cannot be instantia
- The provided class "%s" is an enum, and cannot be instantiat
- An exception was raised while trying to instantiate an insta
- The provided class "%s" does not exist
AI-assisted analysis of doctrine/instantiator@cbb879d6ee (2026-08-21).
Data as JSON: /api/errors/8e789fc6aaa71eca.
Report an issue: GitHub.