{"record":{"id":"3fd6b771758f733b","repo":"phalcon/cphalcon","slug":"a-dependency-injection-container-is-required-to-ac-3fd6b7","errorCode":null,"errorMessage":"A dependency injection container is required to access the 'request' service","messagePattern":"A dependency injection container is required to access the 'request' service","errorType":"exception","errorClass":"Phalcon\\Mvc\\Router\\Exceptions\\RequestServiceUnavailable","httpStatus":null,"severity":"error","filePath":"phalcon/Mvc/Router.zep","lineNumber":1265,"sourceCode":"        let currentHostName = null,\n            routeFound = false,\n            parts = [],\n            params = [],\n            matches = null,\n            this->wasMatched = false,\n            this->matchedRoute = null;\n\n        let eventsManager = this->eventsManager;\n        if eventsManager !== null {\n            eventsManager->fire(\"router:beforeCheckRoutes\", this);\n        }\n\n        /**\n         * Retrieve the request service from the container\n         */\n        let container = <DiInterface> this->container;\n        if container === null {\n            throw new RequestServiceUnavailable();\n        }\n\n        let request = <RequestInterface> container->get(\"request\");\n\n        /**\n         * Build a candidate list of routes that match the request method.\n         * Routes with no HTTP constraint are stored under \"*\" and are always\n         * included. This avoids iterating the full route array per request.\n         */\n        if this->methodRoutesDirty {\n            this->rebuildMethodIndex();\n        }\n\n        let requestMethod   = request->getMethod(),\n            candidateRoutes = [];\n\n        if !fetch candidateRoutes, this->candidatesByMethod[requestMethod] {\n            fetch candidateRoutes, this->candidatesByMethod[\"*\"];","sourceCodeStart":1247,"sourceCodeEnd":1283,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Mvc/Router.zep#L1247-L1283","documentation":"Router::handle() resolves the incoming URI from the 'request' service, which it fetches from the router's DI container. If no container was ever assigned (setDI never called and the router was not resolved through DI), the container is null and handle() aborts with RequestServiceUnavailable before any route matching starts.","triggerScenarios":"Standalone usage: $router = new Router(); $router->handle(); without setDI(); unit tests exercising route matching directly; using the Mvc Router in a CLI worker or micro context where no 'request' service was registered; constructing the router manually in a service provider but forgetting to inject the container.","commonSituations":"Testing routers in isolation (a minimal DI with a request double is needed); moving routing bootstrap out of the main DI setup; Micro apps mixing their own request handling with the full Router; forgetting that handle() reads the URI from the service even when a URI was set explicitly.","solutions":["Inject the container before handling: $router->setDI($di) with a registered 'request' service (Phalcon\\Http\\Request or a double)","Register the router as a DI service ('router' with definition or closure receiving $di) so it is constructed wired-up","For tests, provide a minimal container: $di->set('request', fn() => $requestStub)","Ensure 'request' is registered under exactly that service name before calling handle()"],"exampleFix":"// before\n$router = new \\Phalcon\\Mvc\\Router();\n$router->handle(); // no container -> throws RequestServiceUnavailable\n\n// after\n$di = new \\Phalcon\\Di\\Di();\n$di->set('request', fn() => new \\Phalcon\\Http\\Request());\n$router = new \\Phalcon\\Mvc\\Router(false); // no default routes needed\n$router->setDI($di);\n$router->handle(); // 'request' resolvable","handlingStrategy":"validation","validationCode":"// Ensure the router can resolve 'request' before handling\n$di = $router->getDI();\nif ($di === null || !$di->has('request')) {\n    throw new RuntimeException('Router needs a DI container with a \"request\" service before handle()');\n}\n$router->handle();","typeGuard":"function routerIsWired(\\Phalcon\\Mvc\\Router $router): bool\n{\n    $di = $router->getDI();\n    return $di instanceof \\Phalcon\\Di\\DiInterface && $di->has('request');\n}","tryCatchPattern":"try {\n    $router->handle();\n} catch (\\Phalcon\\Mvc\\Router\\Exceptions\\RequestServiceUnavailable $e) {\n    $router->setDI(bootstrapDi()); // wire a container with 'request', then retry once\n    $router->handle();\n}","preventionTips":["Construct the router through DI (register 'router' as a service) so it is always container-wired","In tests, provide a minimal Di with a request double before calling handle()","Add a bootstrap assertion that getDI() is non-null for any router used standalone"],"tags":["phalcon","router","dependency-injection","request-service"],"backgroundTag":"missing-di-container","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}