fiber 全局错误捕获需显式启用 fiber.recover() 中间件并配置 config.errorhandler,前者捕获 panic 防崩溃,后者定义响应逻辑;业务 error 需通过统一 wrapper 中间件处理,二者不可混用。

全局错误捕获不是靠中间件自动兜底
Fiber 的 app.Use() 中间件默认**不捕获路由处理器中 panic 或未处理的 error**,它只串行执行、无法拦截 panic。你写 panic("boom") 或调用一个没 if err != nil 检查的函数,服务会直接崩溃(除非启用了 recover 机制)。Fiber 本身不内置 panic 捕获,这点和 Express 的 next(err) 风格不同。
必须显式启用 recover 中间件并配置 ErrorHandler
要真正实现“全局错误捕获”,需两步:启用 fiber.Recover() 中间件 + 自定义 Config.ErrorHandler。缺一不可。
-
fiber.Recover()是唯一能捕获 panic 的中间件,必须放在所有路由注册之前(否则 panic 发生时它还没被执行) -
Config.ErrorHandler决定 panic 被捕获后怎么响应——默认是返回 500 + 空体,你要自己写逻辑输出错误详情、打日志、区分环境 - 注意:它**不处理
return errors.New(...)这类普通 error**,那些仍需靠ctx.SendStatus(500)或统一 error 返回封装来处理
panic 捕获 + 业务 error 统一处理要分开设计
真实项目里,你既需要防 panic,也需要把分散的 if err != nil 归到一处处理。推荐组合方案:
- 用
fiber.Recover()拦住 panic,防止进程退出 - 所有路由 handler 都返回
error,并在顶层加一层 wrapper 中间件,比如func(c fiber.Ctx) error { ... return handler(c) },在里面统一检查err并调用c.Status(...).SendString(...) - 别把 panic 处理和业务 error 处理混在同一个
ErrorHandler里——panic 是异常流,业务 error 是正常控制流,堆栈、日志级别、告警策略都该不同
ErrorHandler 里别直接调用 ctx.JSON() 两次
这是高频翻车点:Config.ErrorHandler 函数签名是 func(*fiber.Ctx, error) error,它本身已经是响应阶段。如果你在里面又调用 c.JSON(500, ...),而上层 handler 已经调过一次 c.SendString(),就会触发 http: superfluous response.WriteHeader 错误。
- 务必先检查
c.Response().StatusCode() == 0,再决定是否写响应体 - 更稳妥的做法是:在
ErrorHandler里只做日志和状态码设置,把响应体交给一个预设的模板函数,避免重复写 - 开发期可开启
Config.EnablePrintRoutes = true,快速确认 recover 中间件是否在正确位置生效











