phalcon/cphalcon · error · Phalcon\Container\Exceptions\ServiceNotFound

Service '{name}' not found

Error message

Service '{name}' not found

What it means

Thrown by Container::extend() when the service name (after alias resolution) has no entry in the container's service map. extend() attaches a decorator callable that runs after a service is built, and it only works on names already registered with set(); unlike get(), it never autowires or lazily registers a class name. Hitting this means the decoration target does not exist at the time extend() is called.

Source

Thrown at phalcon/Container/Container.zep:170

     * Extends the definition
     *
     * @param string   $name
     * @param callable $callable
     *
     * @return void
     * @throws CannotExtendResolved
     * @throws ServiceNotFound
     */
    public function extend(string name, callable callableObject) -> void
    {
        let name = this->resolveAlias(name);

        if (array_key_exists(name, this->instances)) {
            throw new CannotExtendResolved(name);
        }

        if (!array_key_exists(name, this->services)) {
            throw new ServiceNotFound(name);
        }

        this->services[name]->addExtender(callableObject);
    }

    /**
     * Resolve and return an element registerd in the container
     *
     * @param string $name
     *
     * @return mixed
     * @throws ServiceNotFound
     */
    public function get(string name) -> mixed
    {
        let name = this->resolveAlias(name);

        if (array_key_exists(name, this->parameters)) {

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Register the service first: $container->set('logger', Logger::class) (or load the ServiceProvider that registers it) before calling extend()
  2. Guard the call: if ($container->hasDefinition('logger')) { $container->extend('logger', $fn); }
  3. Verify the exact name — extend() resolves aliases internally, so the alias target must be a registered service name
  4. If your intent was to decorate an already-built object, register that object with set() instead of extending a definition

Example fix

// before
$container->extend('logger', fn ($l) => $l->pushHandler($handler)); // ServiceNotFound

// after
$container->set('logger', Logger::class);
$container->extend('logger', fn ($l, $c) => $l->pushHandler($handler));
Defensive patterns

Strategy: validation

Validate before calling

if ($container->hasDefinition('logger')) {
    $container->extend('logger', fn ($logger, $c) => $logger->pushHandler($handler));
} else {
    throw new LogicException("Cannot extend 'logger': service is not registered.");
}

Try / catch

use Phalcon\Container\Exceptions\ServiceNotFound;

try {
    $container->extend('logger', $decorator);
} catch (ServiceNotFound $e) {
    // register then retry once, or fail with context
    $container->set('logger', Logger::class);
    $container->extend('logger', $decorator);
}

Prevention

When it happens

Trigger: Calling $container->extend('logger', fn ($logger, $container) => ...) when 'logger' was never passed to set() or registered by a ServiceProvider; passing an alias whose resolved target is not registered; extending before the provider that registers the service has been loaded into the container.

Common situations: Provider ordering during bootstrap (extending in provider A a service registered in provider B that runs later), migrating from Phalcon\Di\DI where service names differ, assuming extend() lazily creates the service like get() does with autowire, or a simple typo in the service name.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/38fbf8af04df6ef7. Report an issue: GitHub.