{"record":{"id":"7e53788dfb3b525a","repo":"slimphp/Slim","slug":"no-base-path-defined","errorCode":null,"errorMessage":"No base path defined.","messagePattern":"No base path defined\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"Slim/Routing/RouteContext.php","lineNumber":85,"sourceCode":"    public function getRoute(): ?RouteInterface\n    {\n        return $this->route;\n    }\n\n    public function getRouteParser(): RouteParserInterface\n    {\n        return $this->routeParser;\n    }\n\n    public function getRoutingResults(): RoutingResults\n    {\n        return $this->routingResults;\n    }\n\n    public function getBasePath(): string\n    {\n        if ($this->basePath === null) {\n            throw new RuntimeException('No base path defined.');\n        }\n        return $this->basePath;\n    }\n}\n","sourceCodeStart":67,"sourceCodeEnd":90,"githubUrl":"https://github.com/slimphp/Slim/blob/80900fb39cafce3ae53b18a2c4f642a122f03095/Slim/Routing/RouteContext.php#L67-L90","documentation":"RouteContext::getBasePath() returns the __basePath__ request attribute, which in a standard Slim app is only set by RouteRunner — the innermost handler — right before it invokes the matched route. If the attribute is null, the context was created from a request that never passed through RouteRunner, so no base path is known and this RuntimeException is thrown. Note RoutingMiddleware sets the parser and routing results but not the base path, so fromRequest() can succeed while getBasePath() still fails.","triggerScenarios":"Calling RouteContext::fromRequest($request)->getBasePath() inside app-level middleware (even after routing middleware ran), because the BASE_PATH attribute is attached later by RouteRunner; reading it in middleware executed before RouteRunner; building RouteContext in unit tests from a request whose attributes were seeded manually without BASE_PATH; replacing RouteRunner with a custom RequestHandler that does not set the attribute.","commonSituations":"Link-builder or breadcrumb middleware that wants the base path for absolute URLs; middleware refactors where code moved out of a route handler into app middleware; test harnesses that craft requests from ServerRequestCreatorFactory without running the full kernel; custom micro-kernels using App as a component without RouteRunner's proxy.","solutions":["Move the getBasePath() call into the route handler or route-level middleware, where RouteRunner has already set the attribute","In app middleware, read $request->getAttribute(RouteContext::BASE_PATH) and treat null as empty instead of calling getBasePath()","If the app is served from a subdirectory, configure it once via $app->setBasePath('/subdir') — but note this alone does not make the attribute available in pre-RouteRunner middleware","In tests, seed the attribute explicitly: $request = $request->withAttribute(RouteContext::BASE_PATH, '/subdir')"],"exampleFix":"// before — app-level middleware, runs before RouteRunner sets __basePath__\n$basePath = RouteContext::fromRequest($request)->getBasePath(); // throws 'No base path defined.'\n\n// after — null-safe attribute read, works at any middleware layer\n$basePath = $request->getAttribute(RouteContext::BASE_PATH) ?? '';","handlingStrategy":"validation","validationCode":"use Slim\\Routing\\RouteContext;\n\n// works at any layer; BASE_PATH is set by RouteRunner before the route handler runs\n$basePathAttr = $request->getAttribute(RouteContext::BASE_PATH);\nif (is_string($basePathAttr)) {\n    $basePath = $basePathAttr;\n} else {\n    // routing done but RouteRunner not reached (app middleware) — use configured value or default\n    $basePath = '';\n}","typeGuard":null,"tryCatchPattern":"try {\n    $basePath = $context->getBasePath();\n} catch (RuntimeException $e) {\n    // only reachable when the attribute is absent (e.g. pre-RouteRunner middleware)\n    $basePath = '';\n}","preventionTips":["Call getBasePath() only in route handlers / route middleware where RouteRunner guarantees the attribute","Prefer reading the attribute with a null coalesce over the throwing getter in middleware code","Set the base path explicitly with $app->setBasePath() when the app runs under a subdirectory","In unit tests, seed the attribute: $request->withAttribute(RouteContext::BASE_PATH, '/subdir')"],"tags":["slim","php","routing","base-path","url-generation","request-attributes"],"backgroundTag":"missing-base-path","analyzedSha":"80900fb39cafce3ae53b18a2c4f642a122f03095","analyzedAt":"2026-08-21T01:41:09.580Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}