doctrine/instantiator · error · Doctrine\Instantiator\Exception\InvalidArgumentException

The provided class "%s" does not exist

Error message

The provided class "%s" does not exist

What it means

This is the fallback branch of fromNonExistingClass(): the given string is not a class, not an interface, and not a trait, so PHP simply does not know the type. It is thrown from getReflectionClass() (src/Instantiator.php:143-144) the moment class_exists($className) returns false, before any reflection happens. In practice it almost always means a typo in the class name or a broken autoloading setup, not a problem inside the library.

Source

Thrown at src/Exception/InvalidArgumentException.php:29

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',
            $reflectionClass->getName(),
        ));
    }

    public static function fromEnum(string $className): self
    {
        return new self(sprintf(

View on GitHub (pinned to cbb879d6ee)

Solutions

  1. Check the class name for typos and exact namespace matches; prefer the ClassName::class constant over hand-built strings.
  2. Run composer dump-autoload and verify the PSR-4 mapping in composer.json matches the file path of the class.
  3. If the name is user/env-supplied, validate it early with class_exists($name) and reject unknown values with a descriptive error at the config boundary.

Example fix

// before
$object = $instantiator->instantiate('App\\Service\\MailServce'); // typo
// InvalidArgumentException: The provided class "App\Service\MailServce" does not exist

// after: use the ::class constant so the IDE and static analysis catch mistakes
use App\Service\MailService;
$object = $instantiator->instantiate(MailService::class);
Defensive patterns

Strategy: validation

Validate before calling

use function class_exists;

if (! class_exists($className)) {
    throw new RuntimeException(sprintf('Unknown class "%s": check spelling and run composer dump-autoload.', $className));
}

$object = (new Instantiator())->instantiate($className);

Type guard

function isKnownClassName(string $className): bool
{
    return class_exists($className); // false for missing classes, interfaces, traits
}

Try / catch

use Doctrine\Instantiator\Exception\InvalidArgumentException;

try {
    $instance = $instantiator->instantiate($className);
} catch (InvalidArgumentException $e) {
    if (str_contains($e->getMessage(), 'does not exist')) {
        // typo or autoload failure — fail loudly with the offending name
        throw new ClassNotFoundException($e->getMessage(), 0, $e);
    }
    throw $e;
}

Prevention

When it happens

Trigger: Calling (new Instantiator())->instantiate($name) with a misspelled FQCN string ('App\Servce\Mailer'), a class whose file is not autoloadable (missing composer PSR-4 mapping, stale vendor/autoload after moving files), or a dynamically built name (concatenated namespace + basename) that does not match any declared class. class_exists() returns false and the 'does not exist' variant is thrown.

Common situations: Typo in a service alias in YAML/XML container config; composer autoload maps are stale after a directory rename or namespace change (fix with composer dump-autoload); the class is defined conditionally inside an if (class_exists(...)) block or by an extension that is not loaded; the class name string lost or gained a leading backslash during string manipulation.

Related errors


AI-assisted analysis of doctrine/instantiator@cbb879d6ee (2026-08-21). Data as JSON: /api/errors/bc3267692bbdcc02. Report an issue: GitHub.