slimphp/Slim · error · RuntimeException
Cannot create RouteContext before routing has been completed
Error message
Cannot create RouteContext before routing has been completed
What it means
RouteContext::fromRequest() builds the context from request attributes (__routeParser__ and __routingResults__) that only Slim's RoutingMiddleware writes onto the request while performing routing. If either attribute is absent, routing has not run yet for this request, so the helper refuses to construct a context. The error is therefore an execution-order problem: your code ran before routing, not a routing failure itself.
Source
Thrown at Slim/Routing/RouteContext.php:37
final class RouteContext
{
public const ROUTE = '__route__';
public const ROUTE_PARSER = '__routeParser__';
public const ROUTING_RESULTS = '__routingResults__';
public const BASE_PATH = '__basePath__';
public static function fromRequest(ServerRequestInterface $serverRequest): self
{
$route = $serverRequest->getAttribute(self::ROUTE);
$routeParser = $serverRequest->getAttribute(self::ROUTE_PARSER);
$routingResults = $serverRequest->getAttribute(self::ROUTING_RESULTS);
$basePath = $serverRequest->getAttribute(self::BASE_PATH);
if ($routeParser === null || $routingResults === null) {
throw new RuntimeException('Cannot create RouteContext before routing has been completed');
}
/** @var RouteInterface|null $route */
/** @var RouteParserInterface $routeParser */
/** @var RoutingResults $routingResults */
/** @var string|null $basePath */
return new self($route, $routeParser, $routingResults, $basePath);
}
private ?RouteInterface $route;
private RouteParserInterface $routeParser;
private RoutingResults $routingResults;
private ?string $basePath;
private function __construct(View on GitHub (pinned to 80900fb39c)
Solutions
- Reorder the stack: call $app->addRoutingMiddleware() as the LAST add* statement, so routing wraps and runs before any middleware that needs RouteContext (last added = executed first)
- Alternatively attach the middleware to specific routes or groups instead of app level — route middleware runs after routing by definition
- In tests, run $routingMiddleware->performRouting($request) (or add the middleware) before asserting on RouteContext
- If RoutingMiddleware is not added at all, add it — relying on RouteRunner means routing happens only at the innermost tip, after every app middleware
Example fix
// before — NavMiddleware added last runs FIRST, before routing: attributes missing $app->addRoutingMiddleware(); $app->add(new NavMiddleware()); // RouteContext::fromRequest() throws // after — routing middleware added last = runs first (outermost) $app->add(new NavMiddleware()); $app->addRoutingMiddleware();
Defensive patterns
Strategy: validation
Validate before calling
use Slim\Routing\RouteContext;
function routingCompleted(Psr\Http\Message\ServerRequestInterface $request): bool
{
return $request->getAttribute(RouteContext::ROUTE_PARSER) !== null
&& $request->getAttribute(RouteContext::ROUTING_RESULTS) !== null;
}
// inside middleware, before using the context:
if (!routingCompleted($request)) {
// either re-order the middleware stack, or route explicitly:
$request = $routingMiddleware->performRouting($request);
}
$context = RouteContext::fromRequest($request); Prevention
- Standardize stack assembly: $app->addRoutingMiddleware() always the last add* call in bootstrap, so routing runs before all middleware that read route attributes
- Wrap RouteContext::fromRequest() in a small app-level helper that checks the attributes first and fails with 'routing not run — check middleware order'
- In tests, run performRouting() or the routing middleware before touching RouteContext
- Code-review rule: any middleware calling RouteContext must sit after routing in the execution order
When it happens
Trigger: Calling RouteContext::fromRequest($request) inside an app-level middleware that executes before RoutingMiddleware. In Slim 4 the last middleware added via $app->add() runs first (outermost), so adding your middleware AFTER $app->addRoutingMiddleware() in code makes yours execute before routing. Also triggered when RoutingMiddleware is never added (RouteRunner only performs routing at the innermost tip, after all middleware) or in tests that call $app->handle() on a request that skipped routing.
Common situations: Middleware that generates URLs (menus, pagination, API links) calling fromRequest() but registered in the wrong order relative to $app->addRoutingMiddleware(); refactoring from route-level middleware to app-level middleware; unit tests constructing ServerRequests from globals without running performRouting(); upgrading from Slim 3 where $app->request->getRouteInfo() habits carried over.
Related errors
- No base path defined.
- Route collector cache file directory `%s` is not writable
- Named route does not exist for name: %s
- Route not found, looks like your route cache is stale.
- Missing data for URL segment: %s
AI-assisted analysis of slimphp/Slim@80900fb39c (2026-08-21).
Data as JSON: /api/errors/5a308e66d0850acc.
Report an issue: GitHub.