barryvdh/laravel-ide-helper · error · ReflectionException

Class '$class' not found.

Error message

Class '$class' not found.

What it means

Thrown by a temporary autoloader that ide-helper:meta registers while it resolves every container binding (src/Console/MetaCommand.php:188-216). Its purpose is to turn a silent autoload miss into a loud ReflectionException naming the missing class, so broken bindings surface during meta generation instead of producing an incomplete .php.meta file. It stays quiet only when the miss originates from class_exists()/interface_exists()/trait_exists()/enum_exists(), which expect a graceful return. In practice the message tells you that some class referenced by a container binding, provider, or config value cannot be autoloaded.

Source

Thrown at src/Console/MetaCommand.php:210

        $autoloader = function ($class) use ($aliases) {
            // ignore aliases as they're meant to be resolved elsewhere
            if (in_array($class, $aliases, true)) {
                return;
            }

            // Don't throw when class existence is being checked via class_exists(),
            // interface_exists(), trait_exists(), or enum_exists(). These functions
            // expect the autoloader to return gracefully when the class doesn't exist.
            // Throwing here would break libraries that use class_exists() to check for
            // optional dependencies (e.g. Doctrine ORM checking for removed classes).
            $existsFunctions = ['class_exists', 'interface_exists', 'trait_exists', 'enum_exists'];
            foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3) as $frame) {
                if (isset($frame['function']) && in_array($frame['function'], $existsFunctions, true)) {
                    return;
                }
            }

            throw new \ReflectionException("Class '$class' not found.");
        };

        spl_autoload_register($autoloader);

        return $autoloader;
    }

    protected function getExpectedArgumentSets()
    {
        return [
            'auth' => $this->loadTemplate('auth')->keys()->filter()->toArray(),
            'configs' => $this->loadTemplate('configs')->pluck('name')->filter()->toArray(),
            'middleware' => $this->loadTemplate('middleware')->keys()->filter()->toArray(),
            'routes' => $this->loadTemplate('routes')->pluck('name')->filter()->toArray(),
            'views' => $this->loadTemplate('views')->pluck('key')->filter()->map(function ($value) {
                return (string) $value;
            })->toArray(),
            'translations' => $this->loadTemplate('translations')->filter()->keys()->toArray(),

View on GitHub (pinned to 3a886dca5c)

Solutions

  1. Run `composer install` (or `composer dump-autoload -o`) so the autoloader maps every installed class, then retry `php artisan ide-helper:meta -v`.
  2. Re-run with -v/--verbose: the wrapping 'Cannot make ...' comment in handle() prints the abstract name together with this ReflectionException message, telling you exactly which class is missing.
  3. Search the codebase and config for the missing class name (config/app.php providers, bootstrap/providers.php, Auth model config, custom service providers) and remove or update the stale reference.
  4. If the class belongs to an optional package, either reinstall the package (`composer require vendor/pkg`) or make the binding/provider conditional on class_exists().
  5. If names were moved by a framework upgrade, update the imports in your own providers and re-run `composer dump-autoload`.

Example fix

# before: stale provider references a removed package class
# config/app.php
App\Providers\OldSmsProvider::class,  # binds App\Services\Sms\Sender which no longer exists
$ php artisan ide-helper:meta
Class 'App\Services\Sms\Sender' not found.

# after: drop the dead provider and refresh the autoloader
# config/app.php
# (OldSmsProvider removed)
$ composer dump-autoload -o && php artisan ide-helper:meta -v
Defensive patterns

Strategy: try-catch

Validate before calling

// Preflight before ide-helper:meta: surface bindings that cannot resolve
$failures = [];
foreach (array_keys(app()->getBindings()) as $abstract) {
    try {
        app()->make($abstract);
    } catch (\Throwable $e) {
        $failures[] = $abstract . ' => ' . $e->getMessage();
    }
}
if ($failures) {
    fwrite(STDERR, implode("\n", $failures) . "\n");
    exit(1); // fix composer autoload / stale references before generating
}

Try / catch

try {
    \Artisan::call('ide-helper:meta', ['--verbose' => true]);
} catch (\ReflectionException $e) {
    // getMessage() names the missing class; repair vendor/config and re-run
    report($e);
}

Prevention

When it happens

Trigger: Running `php artisan ide-helper:meta` when a bound concrete class does not exist: composer dependencies not installed, an optimized/stale autoloader still pointing at deleted files, a service provider or config entry referencing a class from a package that was removed or renamed, or vendor code that instantiates an optional dependency without a class_exists() guard. The throw happens only when the missing class is actually used (instantiated/reflected), not merely existence-checked.

Common situations: CI or fresh clone where `composer install` was skipped or ran with --no-dev; after deleting a package while keeping its ProviderEntry in config/app.php or bootstrap/providers.php; after a major Laravel/package upgrade that moved or renamed classes while composer dump-autoload -o caches old paths; a config value (e.g. auth.model or a custom binding) pointing at a deleted model namespace.

Related errors


AI-assisted analysis of barryvdh/laravel-ide-helper@3a886dca5c (2026-08-23). Data as JSON: /api/errors/053878104327b56f. Report an issue: GitHub.