fiber.config.errorhandler 是 fiber 唯一全局错误捕获入口,仅在 fiber.new() 初始化时通过 config 配置生效,专捕路由匹配成功后 handler 中的 panic 或 fiber.error,需手动设状态码,非 fiber.error 统一视为 500,且须前置 middleware.recover() 防崩溃。

fiber.Config.ErrorHandler 是唯一入口
Fiber 的全局错误捕获只在 fiber.New() 初始化时通过 ErrorHandler 配置项生效,后期无法覆盖。它不处理 404(那是 NotFound 的事),只负责捕获路由匹配成功后、handler 执行中发生的 panic 或显式抛出的 *fiber.Error。
- 必须在
fiber.New(fiber.Config{...})中传入,不能用app.Use(...)或其他方式“补救” - 函数签名固定为
func(*fiber.Ctx, error) error,第二个参数就是原始错误 - 它不会自动调用
c.Status(),必须手动设置状态码,否则默认是 200 - 若 handler 内用了
panic("xxx"),且没配middleware.Recover(),会直接崩溃——所以ErrorHandler前建议加middleware.Recover()
区分 404 和 500 要靠类型断言
ErrorHandler 收到的 error 可能是 *fiber.Error(比如 c.SendString().Err 或 fiber.NewError(500, "msg")),也可能是普通 panic 转来的未识别错误。不能只看错误消息字符串来判断状态码。
- 用
if e, ok := err.(*fiber.Error); ok判断是否为 Fiber 自身错误,然后取e.Code - 非
*fiber.Error类型一律视为 500,例如recover()捕获的 panic - 别忘了在
c.SendString()前调用c.Status(...),否则浏览器看到 HTML 却收到 200 状态
ErrorHandler: func(c *fiber.Ctx, err error) {
if e, ok := err.(*fiber.Error); ok {
c.Status(e.Code)
} else {
c.Status(500)
}
c.SendString(fmt.Sprintf("<h1>%d 错误</h1>", c.Response().StatusCode()))
}
模板渲染不能直接塞进 ErrorHandler
如果你用了 html.New() 模板引擎,不要在 ErrorHandler 里直接写 c.Render("error", nil)。因为 Render 是异步方法,而 ErrorHandler 是同步执行上下文,错误可能被忽略或 panic。
- 要么改用
c.SendString(htmlContent)预加载模板内容(适合简单页面) - 要么把模板渲染逻辑封装成同步函数,在
ErrorHandler中调用并显式处理错误 - 更稳妥的做法:提前用
template.ParseFiles()加载好模板,ErrorHandler中只做Execute并检查返回值
容易被忽略的中间件顺序问题
ErrorHandler 不是“万能兜底”,它只对进入路由 handler 后的错误有效。如果某个中间件(比如鉴权中间件)提前 return c.Status(401).SendString(...),那这个响应就绕过了 ErrorHandler。
-
middleware.Recover()必须在ErrorHandler生效路径上,推荐放在所有业务中间件之前 -
middleware.Logger()放在Recover之后,否则 panic 日志可能漏掉 - 自定义中间件里如果调用
c.Next()后没检查c.Response().StatusCode(),可能掩盖真实错误状态











