{"record":{"id":"695c2097803e18f7","repo":"phalcon/cphalcon","slug":"a-dependency-injection-container-is-required-to-ac-695c20","errorCode":null,"errorMessage":"A dependency injection container is required to access the 'annotations' service","messagePattern":"A dependency injection container is required to access the 'annotations' service","errorType":"exception","errorClass":"Phalcon\\Mvc\\Router\\Exceptions\\AnnotationsServiceUnavailable","httpStatus":null,"severity":"error","filePath":"phalcon/Mvc/Router/Annotations.zep","lineNumber":114,"sourceCode":"        return this->handlers;\n    }\n\n    /**\n     * Produce the routing parameters from the rewrite information\n     */\n    public function handle( string uri) -> void\n    {\n        var annotationsService, handlers, controllerSuffix, scope, prefix,\n            route, compiledPattern, container, handler, controllerName,\n            lowerControllerName, namespaceName, moduleName, handlerAnnotations,\n            classAnnotations, annotations, annotation, methodAnnotations, method,\n            collection;\n        string sufixed;\n\n        let container = <DiInterface> this->container;\n\n        if unlikely typeof container != \"object\" {\n            throw new AnnotationsServiceUnavailable();\n        }\n\n        let handlers = this->handlers;\n        let controllerSuffix = this->controllerSuffix;\n        let annotationsService = container->getShared(\"annotations\");\n\n        for scope in handlers {\n            if typeof scope != \"array\" {\n                continue;\n            }\n\n            /**\n             * A prefix (if any) must be in position 0\n             */\n            let prefix = scope[0];\n\n            if !empty prefix {\n                /**","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Mvc/Router/Annotations.zep#L96-L132","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Attach a container: $router = new Router\\Annotations(); $router->setDI(new \\Phalcon\\Di\\FactoryDefault()); then add handlers and call handle()","In full applications, reuse the existing DI: $router->setDI($application->getDI()) or via Di::getDefault()","If using a hand-built Di, ensure it can resolve 'annotations' (register Annotations\\Adapter) — the container check passes, but the service must exist"],"exampleFix":"// before\n$router = new \\Phalcon\\Mvc\\Router\\Annotations(false);\n$router->addResource('App\\Controllers\\Posts');\n$router->handle('/posts'); // no DI container set\n\n// after\n$di     = new \\Phalcon\\Di\\FactoryDefault();\n$router = new \\Phalcon\\Mvc\\Router\\Annotations(false);\n$router->setDI($di);\n$router->addResource('App\\Controllers\\Posts');\n$router->handle('/posts');","handlingStrategy":"type-guard","validationCode":"// ensure a container exists before the Annotations router handles anything\n$di = \\Phalcon\\Di\\Di::getDefault();\nif ($di === null) {\n    $di = new \\Phalcon\\Di\\FactoryDefault();\n    \\Phalcon\\Di\\Di::setDefault($di);\n}\n\n$router->setDI($di);\n$router->handle($uri);","typeGuard":"function hasContainer(\\Phalcon\\Mvc\\RouterInterface $router): bool\n{\n    $di = method_exists($router, 'getDI') ? $router->getDI() : null;\n    return $di instanceof \\Phalcon\\Di\\DiInterface;\n}","tryCatchPattern":"try {\n    $router->handle($uri);\n} catch (\\Phalcon\\Mvc\\Router\\Exceptions\\AnnotationsServiceUnavailable $e) {\n    $logger->error('Annotations router used without DI container');\n    throw new RuntimeException('Router bootstrap incomplete: attach a DI container', 0, $e);\n}","preventionTips":["Always call $router->setDI($di) right after constructing an Annotations router, in app code and tests alike","Register or verify the 'annotations' service in custom containers before first handle()","In unit tests, inject a container with a stub annotations adapter to avoid full bootstrapping"],"tags":["phalcon","router","annotations","di-container","bootstrap"],"backgroundTag":"missing-di-container","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}