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

  1. 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)
  2. Alternatively attach the middleware to specific routes or groups instead of app level — route middleware runs after routing by definition
  3. In tests, run $routingMiddleware->performRouting($request) (or add the middleware) before asserting on RouteContext
  4. 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

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


AI-assisted analysis of slimphp/Slim@80900fb39c (2026-08-21). Data as JSON: /api/errors/5a308e66d0850acc. Report an issue: GitHub.