Buffalo 默认错误页位于 templates/error/404.plush.html 和 templates/error/500.plush.html,使用 Plush 模板引擎渲染,通过 App.ErrorHandler 转发,错误对象以变量 err 注入模板。

Buffalo 默认错误页在哪找
Buffalo 默认会把 /error 请求交给 App.ErrorHandler 处理,但这个 handler 本身不渲染页面——它只是转发给模板引擎。真正起作用的是你放在 templates/error/ 目录下的 HTML 文件。
关键路径是:templates/error/404.plush.html 和 templates/error/500.plush.html(注意后缀是 .plush.html,不是 .html)。Buffalo 使用 Plush 模板引擎,不识别纯 HTML 文件。
- 文件名必须严格为
404.plush.html、500.plush.html,大小写和扩展名都不能错 - 目录必须是
templates/error/,不能是templates/errors/或assets/error/ - 如果用了
buffalo dev,改完文件要重启服务;用buffalo build打包后,这些文件会被嵌入二进制,无需额外部署静态资源
Plush 模板里怎么拿到错误信息
Buffalo 在渲染错误页时,会把当前错误对象注入模板上下文,变量名为 err。你可以在 404.plush.html 中直接用 输出错误消息,但要注意:404 场景下 err 通常是 echo.HTTPError 或 Buffalo 自己的路由未匹配错误,内容较简略;而 500 页面里的 err 才是真实 panic 或 handler 抛出的原始 error。
Buffalo框架 1.0.1 版本源码包下载,适合需要错误处理改进、依赖更新、render.Download 注释和 request logger 调整的 v1 项目。
- 推荐统一加一层判断:
Page not found - 不要在错误页里调用可能 panic 的函数(比如访问
err.Unwrap()而不判空),否则会触发二级 500 - 若需区分开发/生产环境显示详情,可用
app.Environment == "development"判断,但别把 stack trace 直接吐给线上用户
为什么改了 404.plush.html 还是看不到效果
最常见原因是模板没被重新编译进二进制,或路径/命名不规范导致 Buffalo 根本没加载它。
- 运行
buffalo build后检查输出日志,确认是否打印了embedding templates/error/404.plush.html类似行;没出现说明文件位置或命名有误 - 删掉
tmp/目录再试一次buffalo dev,旧缓存可能导致模板未更新 - 用 curl 测试:
curl -I http://localhost:3000/nonexistent看响应头是否为HTTP/1.1 404 Not Found;如果是 200,说明你写的路由或中间件提前拦截并返回了页面(比如某个通配路由app.GET("/{path:.+}")没加限制) - 检查有没有自定义过
App.ErrorHandler—— 如果你在app.go里显式调用了app.ErrorHandler = func(...),那 Buffalo 就完全跳过模板机制,走你写的逻辑
想让 404 和 500 返回 JSON 而不是 HTML 怎么办
Buffalo 默认只对浏览器请求返回 HTML 错误页;API 场景下,你得手动接管错误响应格式。核心是重写 App.ErrorHandler,并在里面判断 Accept 请求头。
app.ErrorHandler = func(status int, err error, c buffalo.Context) error {
if strings.Contains(c.Request().Header.Get("Accept"), "application/json") {
return c.Render(status, r.JSON(map[string]string{
"error": err.Error(),
"status": http.StatusText(status),
}))
}
return c.Error(status, err)
}
- 这段代码必须放在
app.go中app = buffalo.New(buffalo.Options{...})之后、app.Serve()之前 -
c.Error(status, err)是调回默认逻辑,它才会去查templates/error/;直接return nil或漏掉这句,错误就静默了 - 别在
ErrorHandler里做耗时操作(如写日志到磁盘),它在主请求链路中执行,会影响所有错误响应延迟
真正难处理的其实是中间件里 panic 的捕获点——比如某个自定义中间件没 defer recover,就会绕过 ErrorHandler 直接触发进程级 panic。这种必须在 app.Use() 前加全局 recover 中间件,否则连 500 都不会走你定义的流程。

















