laravel/framework · error · InvalidArgumentException

Unable to find observer: {$class}

Error message

Unable to find observer: {$class}

What it means

When registering an observer via Model::observe($class), resolveObserverClassName() requires the supplied string (or object's class) to actually exist. A non-existent class string is rejected up-front because binding event listeners against it would silently no-op.

Source

Thrown at src/Illuminate/Database/Eloquent/Concerns/HasEvents.php:123

    /**
     * Resolve the observer's class name from an object or string.
     *
     * @param  object|string  $class
     * @return class-string
     *
     * @throws \InvalidArgumentException
     */
    private function resolveObserverClassName($class)
    {
        if (is_object($class)) {
            return get_class($class);
        }

        if (class_exists($class)) {
            return $class;
        }

        throw new InvalidArgumentException('Unable to find observer: '.$class);
    }

    /**
     * Get the observable event names.
     *
     * @return string[]
     */
    public function getObservableEvents()
    {
        return array_merge(
            [
                'retrieved', 'creating', 'created', 'updating', 'updated',
                'saving', 'saved', 'restoring', 'restored', 'replicating',
                'trashed', 'deleting', 'deleted', 'forceDeleting', 'forceDeleted',
            ],
            $this->observables
        );
    }

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Verify the FQN matches the file location (PSR-4) and the class exists.
  2. Run composer dump-autoload to refresh the classmap.
  3. Pass the ::class constant (Post::observe(AuditObserver::class)) instead of a literal string to catch typos at IDE/static-analysis time.

Example fix

// before
Post::observe('App\Observer\PostObserver'); // wrong namespace 'Observer' vs 'Observers'

// after
Post::observe(\App\Observers\PostObserver::class);
Defensive patterns

Strategy: validation

Validate before calling

if (! class_exists($observerClass)) {
    throw new \InvalidArgumentException("Observer class not found: {$observerClass}");
}
Post::observe($observerClass);

Type guard

function observerClassExists(string $class): bool
{
    return class_exists($class);
}

Try / catch

try {
    Post::observe(\App\Observers\PostObserver::class);
} catch (\InvalidArgumentException $e) {
    if (str_contains($e->getMessage(), 'Unable to find observer')) {
        \Illuminate\Support\Facades\Artisan::call('optimize:clear');
        report('Observer class missing; cleared autoload cache');
    }
    throw $e;
}

Prevention

When it happens

Trigger: Calling Post::observe('App\Observers\AuditObserver') when that class is not autoloadable: wrong namespace, typo, file not yet created, or composer autoload cache stale.

Common situations: Observer created in a non PSR-4 path; renamed namespace but boot reference not updated; package observers referenced without installing the package; stale composer dump-autoload after a move.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/b75ceef18527e0b8.json. Report an issue: GitHub.