Skip to content

@nocache throws a TypeError when rendered outside a matched route #15214

Description

@ssang

Bug description

@nocache throws a TypeError instead of rendering when the view is rendered outside a matched route.

Statamic\StaticCaching\NoCache\BladeDirective::handle() calls Cache::isBeingUsedOnCurrentRoute() on every render, and that method passes request()->route() straight into Router::gatherRouteMiddleware(), which typehints Route:

// src/StaticCaching/Middleware/Cache.php
public static function isBeingUsedOnCurrentRoute()
{
    return in_array(static::class, app('router')->gatherRouteMiddleware(request()->route()));
}

When no route has matched, request()->route() is null and the typed parameter fatals.

The notable part is that BladeDirective already has the right behaviour for this case — it renders the region inline when static caching isn't active on the route:

if (! Cache::isBeingUsedOnCurrentRoute()) {
    return view($view, $context)->render();
}

A routeless render is unambiguously "static caching is not active here", so this should take that fallback. Instead the check fatals before it can be reached, and a context that ought to degrade gracefully 500s.

The error message also points at static caching rather than at the real cause (a view rendered without a route), which makes it awkward to diagnose.

How to reproduce

  1. Add resources/views/probe.blade.php containing <p>region</p>
  2. Render a @nocache of it with no matched route — e.g. php artisan tinker:
config(['statamic.static_caching.strategy' => 'half']);

Blade::render('@nocache("probe")');
// TypeError

request()->setRouteResolver(fn () => new Illuminate\Routing\Route('GET', '/', fn () => ''));
Blade::render('@nocache("probe")');
// <p>region</p>

The first call throws; the second correctly takes the inline fallback.

How we hit it: a feature test that renders a Blade component tree containing a @nocache region via Blade::render(), with no HTTP request. The same applies to any non-HTTP render of page content (a PDF or email render, for instance).

Logs

Illuminate\Routing\Router::gatherRouteMiddleware(): Argument #1 ($route) must be of type
Illuminate\Routing\Route, null given, called in
vendor/statamic/cms/src/StaticCaching/Middleware/Cache.php on line 268

Environment

Statamic 6.27.2 Pro, Laravel 13.25.0, PHP 8.5.8, application static caching driver (half)

Installation

Existing Laravel app

Additional details

A null guard would make the existing fallback reachable:

public static function isBeingUsedOnCurrentRoute()
{
    if (! $route = request()->route()) {
        return false;
    }

    return in_array(static::class, app('router')->gatherRouteMiddleware($route));
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions