Skip to content

[6.x] Hydrate cascade for error views rendered outside Statamic's exception stack - #15201

Open
wakqasahmed wants to merge 1 commit into
statamic:6.xfrom
wakqasahmed:fix/issue-14167-cascade-hydration-non-statamic-error
Open

[6.x] Hydrate cascade for error views rendered outside Statamic's exception stack#15201
wakqasahmed wants to merge 1 commit into
statamic:6.xfrom
wakqasahmed:fix/issue-14167-cascade-hydration-non-statamic-error

Conversation

@wakqasahmed

Copy link
Copy Markdown

Fixes #14167

Problem

Statamic's own HTTP exception classes (Statamic\Exceptions\NotFoundHttpException, ForbiddenHttpException, UnauthorizedHttpException) hydrate the cascade via RendersHttpExceptions::contents() before rendering an errors.{status} Antlers template. That's the only place that calls Cascade::instance()->hydrate().

A 404 (or other HTTP error) thrown from outside Statamic's own stack — e.g. Livewire's default 404 handling, which throws Symfony's stock NotFoundHttpException rather than Statamic's subclass — never goes through that path. Laravel falls back to its default exception rendering, which renders the Antlers error template directly with no cascade hydrated. Any {{ global_set_variable }} reference in that template then throws a BadMethodCallException.

The CP route group already gets its own exception handler swapped in via SwapCpExceptionHandler middleware, but the front-end route group has no equivalent, and that middleware only covers Statamic's own exception classes anyway — a generic Symfony exception bypasses it either way since it doesn't define its own render() method.

Fix

Registers a renderable() callback on the app's exception handler (src/Providers/AppServiceProvider.php) that:

  • Skips CP/API routes and JSON requests (already handled elsewhere).
  • Only engages when a matching errors.{status} view exists.
  • Hydrates the cascade and renders the error template through Statamic's View class, the same way RendersHttpExceptions::contents() does.

This only fires for exceptions that don't already define their own render() method (Statamic's own exception classes are checked first by Laravel and never reach this callback), and it's discarded for CP routes since SwapCpExceptionHandler rebinds the exception handler singleton to ControlPanelExceptionHandler, which has its own render() that doesn't consult renderable() callbacks.

Test plan

  • Added it_hydrates_the_cascade_for_a_404_thrown_outside_of_statamics_own_exception_stack to tests/FrontendTest.php, which throws a bare Symfony\Component\HttpKernel\Exception\NotFoundHttpException from an ad-hoc route (mirroring Livewire's default 404 path) with an errors.404 template referencing a global set variable via colon syntax, and asserts it renders successfully.
  • Not run locally — this environment doesn't have a PHP runtime available, so the test is written but unverified here. Written following the existing conventions in tests/FrontendTest.php (FakesViews, withFakeViews/viewShouldReturnRaw) and tests/View/CascadeTest.php (GlobalSet setup). Relying on CI to validate.

… stack (statamic#14167)

Statamic's own HTTP exception classes (NotFoundHttpException,
ForbiddenHttpException, UnauthorizedHttpException) hydrate the cascade
via RendersHttpExceptions::contents() before rendering an Antlers
error template. A generic exception thrown outside that stack (e.g.
Livewire's default 404 handling, which throws Symfony's stock
NotFoundHttpException) never goes through that path, so referencing
a global in the error template throws a BadMethodCallException.

Register a renderable callback on the app's exception handler that
hydrates the cascade and renders the error template through
Statamic's View class whenever a generic HttpExceptionInterface
exception has a matching errors.{status} view, regardless of which
middleware stack or exception class triggered it.
@duncanmcclean duncanmcclean changed the title Hydrate cascade for error views rendered outside Statamic's exception stack (#14167) [6.x] Hydrate cascade for error views rendered outside Statamic's exception stack Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error accessing globals from non-Statamic 404 page

1 participant