phalcon/cphalcon · error · Phalcon\Mvc\Router\Exceptions\AnnotationsServiceUnavailable

A dependency injection container is required to access the '

Error message

A dependency injection container is required to access the 'annotations' service

What it means

The Annotations router reads controller/method annotations through the shared 'annotations' service, which it resolves from the dependency injection container. AnnotationsRouter::handle() first asserts that a DI container is present; with no container attached (or a non-object container) it throws AnnotationsServiceUnavailable before any controller scanning begins.

Source

Thrown at phalcon/Mvc/Router/Annotations.zep:114

        return this->handlers;
    }

    /**
     * Produce the routing parameters from the rewrite information
     */
    public function handle( string uri) -> void
    {
        var annotationsService, handlers, controllerSuffix, scope, prefix,
            route, compiledPattern, container, handler, controllerName,
            lowerControllerName, namespaceName, moduleName, handlerAnnotations,
            classAnnotations, annotations, annotation, methodAnnotations, method,
            collection;
        string sufixed;

        let container = <DiInterface> this->container;

        if unlikely typeof container != "object" {
            throw new AnnotationsServiceUnavailable();
        }

        let handlers = this->handlers;
        let controllerSuffix = this->controllerSuffix;
        let annotationsService = container->getShared("annotations");

        for scope in handlers {
            if typeof scope != "array" {
                continue;
            }

            /**
             * A prefix (if any) must be in position 0
             */
            let prefix = scope[0];

            if !empty prefix {
                /**

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Attach a container: $router = new Router\Annotations(); $router->setDI(new \Phalcon\Di\FactoryDefault()); then add handlers and call handle()
  2. In full applications, reuse the existing DI: $router->setDI($application->getDI()) or via Di::getDefault()
  3. If using a hand-built Di, ensure it can resolve 'annotations' (register Annotations\Adapter) — the container check passes, but the service must exist

Example fix

// before
$router = new \Phalcon\Mvc\Router\Annotations(false);
$router->addResource('App\Controllers\Posts');
$router->handle('/posts'); // no DI container set

// after
$di     = new \Phalcon\Di\FactoryDefault();
$router = new \Phalcon\Mvc\Router\Annotations(false);
$router->setDI($di);
$router->addResource('App\Controllers\Posts');
$router->handle('/posts');
Defensive patterns

Strategy: type-guard

Validate before calling

// ensure a container exists before the Annotations router handles anything
$di = \Phalcon\Di\Di::getDefault();
if ($di === null) {
    $di = new \Phalcon\Di\FactoryDefault();
    \Phalcon\Di\Di::setDefault($di);
}

$router->setDI($di);
$router->handle($uri);

Type guard

function hasContainer(\Phalcon\Mvc\RouterInterface $router): bool
{
    $di = method_exists($router, 'getDI') ? $router->getDI() : null;
    return $di instanceof \Phalcon\Di\DiInterface;
}

Try / catch

try {
    $router->handle($uri);
} catch (\Phalcon\Mvc\Router\Exceptions\AnnotationsServiceUnavailable $e) {
    $logger->error('Annotations router used without DI container');
    throw new RuntimeException('Router bootstrap incomplete: attach a DI container', 0, $e);
}

Prevention

When it happens

Trigger: Creating `new Router\Annotations()` in a unit test or standalone script and calling handle('/uri') without setDI(); a micro-app that never booted FactoryDefault; the container was set on a different router instance or reset to null.

Common situations: PHPUnit tests constructing the router directly; CLI scripts reusing router classes outside the MVC stack; refactoring bootstrap so the router is built before the DI container exists.

Related errors


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