Error accessing globals from non-Statamic 404 page
维护者通常 1 天内回复
还没有人认领这个 Issue。
- #15201 来自 @wakqasahmed —— 已关闭,未合并
评估
调研方向
Start by reading resources/views/errors/404.antlers.html and tracing how SwapExceptionHandler hydrates the Cascade. Then investigate how Laravel renders Antlers error templates for Livewire requests that lack the X-Livewire header, including the suggested exception-rendering approach. Done means the 404 template can resolve its global values in this case without throwing BadMethodCallException.
由索引模型根据 Issue 内容生成。
描述
I intermittently get this error in Laravel Nightwatch. Is this something that could be fixed with an update?
BadMethodCallException: Call to undefined method errorHeadline.
The Problem:
I was getting a BadMethodCallException: Call to undefined method errorHeadline in production, triggered by bots/scanners hitting the Livewire update endpoint directly (POST to /livewire-{hash}/update without the X-Livewire header).
The 404 error template (resources/views/errors/404.antlers.html) was pulling content from a 404 global set using the standard colon syntax:
{{ 404:error_headline }}
{{ 404:error_text }}
Root Cause:
Livewire registers its update route with only the web middleware group , it doesn't include Statamic's SwapExceptionHandler middleware, which is what hydrates the Cascade with global set data.
When Livewire's RequireLivewireHeaders middleware detects a request without the X-Livewire header, it calls abort(404). Laravel's default exception handler then renders the errors/404.antlers.html view through the Antlers engine, but without the Cascade being hydrated.
Without the Cascade, the Antlers runtime can't resolve 404 as a global set handle. It falls through to treating 404 as a tag name and attempts to call errorHeadline() as a method on Statamic\Tags\Tags via __call() — which throws BadMethodCallException.
The ?? (null coalescence) operator doesn't help either {{ 404:error_headline ?? 'fallback' }} still throws, because the exception happens during tag resolution before the fallback operator evaluates.
How to Reproduce:
From the browser console on any page with a valid session:
const token = decodeURIComponent(
document.cookie.split('; ').find(c => c.startsWith('XSRF-TOKEN='))?.split('=')[1]
);
fetch('/livewire-YOUR_HASH_HERE/update', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-XSRF-TOKEN': token }
// deliberately no X-Livewire header
}).then(r => r.text()).then(console.log)
You can find your Livewire endpoint hash with php artisan route:list | grep livewire.
Fix:
I hardcoded the content in the 404 template, removing all {{ 404:... }} references. The global set colon syntax ({{ handle:field }}) relies on the Cascade and can't be used safely in error templates that may be rendered outside Statamic's rendering pipeline.
Takeaway:
If you're using Antlers for your error templates (resources/views/errors/*.antlers.html), be aware that they can be rendered by Laravel's exception handler without Statamic's Cascade. Avoid global set references using the colon syntax ({{ global_handle:field }}). Either hardcode the values or use a Blade template with PHP to load globals via Statamic\Facades\GlobalSet::findByHandle().
I asked Claude if there's a fix? It suggested:
Statamic could hydrate the Cascade in the exception handler
Statamic's SwapExceptionHandler middleware is what sets up the Cascade for front-end routes. But routes outside Statamic's middleware stack (like Livewire's) use Laravel's default exception handler, which renders the Antlers 404 view without the Cascade. Statamic could register a global exception renderer (via Exceptions::render() in bootstrap/app.php or a service provider) that ensures the Cascade is hydrated before rendering any Antlers error template, regardless of which middleware stack the request went through.
Environment
Application Name: Statamic
Laravel Version: 12.53.0
PHP Version: 8.4.18
Composer Version: 2.9.5
Environment: local
Debug Mode: OFF
URL: website.test
Maintenance Mode: OFF
Timezone: America/New_York
Locale: en
Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED
Drivers
Broadcasting: log
Cache: redis
Database: sqlite
Logs: stack / single
Mail: smtp
Queue: sync
Session: redis
Storage
public/storage: NOT LINKED
Livewire
Livewire: v4.2.1
Statamic
Addons: 5
Sites: 1
Stache Watcher: Enabled
Static Caching: Disabled
Version: 5.73.11 PRO
Statamic Addons
marcorieser/statamic-live-search: 3.1.1
marcorieser/statamic-livewire: 5.2.1
statamic/collaboration: 1.0.1
statamic/importer: 1.9.0
visuellverstehen/statamic-anchor-navigation: 1.0.0
- 主要语言
- PHP
- 星标
- 4.9k
- 派生
- 647
- 平均合并
- 1 天 20 小时
- 30 天内合并 PR
- 113
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
statamic/cms 的其他 Issue
-
preferences
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 74/100
维护者通常 1 天内回复
-
accessibility
难度 2/5 1-3 小时 新手友好度 74/100
维护者通常 1 天内回复
-
antlers
难度 2/5 1-3 小时 新手友好度 66/100
维护者通常 1 天内回复
-
navigations
难度 3/5 1-2 天 新手友好度 68/100
维护者通常 1 天内回复
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 72/100
Automattic/blocks-engine#2803 ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 72/100
hestiacp/hestiacp#5798 · 2 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 62/100
woocommerce/woocommerce-google-analytics-integration#699 ·
维护者通常 1 天内回复
-
Sidebar highlights two items when plugin routes share a prefix (/plugin/foo and /plugin/foo-bar)未关闭
难度 2/5 1-3 小时 新手友好度 72/100
getgrav/grav-plugin-admin2#195 ·
-
难度 2/5 1-3 小时 新手友好度 60/100
维护者通常 1 天内回复