Fiber错误暴露因无隐式兜底,需手动配置:recover必须首注册、响应提交后不可再调Next、NotFound须初始化时传入。

报错不是框架问题,八成是中间件顺序、响应已提交、或配置时机不对——Fiber 不做隐式兜底,所有错误都直接暴露。
中间件注册顺序错了,panic 就捕不到
Fiber 的 fiber.Recover() 必须在所有其他中间件之前调用,否则 panic 会直接 crash 进程,连日志都不留。常见错误是把它写在 app.Use(fiber.Logger()) 或权限中间件后面。
- 正确顺序:
app.Use(fiber.Recover())→app.Use(authMiddleware)→app.Get("/api", handler) - 错误写法:
app.Use(authMiddleware)后再加app.Use(fiber.Recover()),此时 auth 中 panic 已无法被捕获 - 调试技巧:在每个中间件开头加
log.Printf("→ %s", "name"),看 panic 前最后输出的是哪个,就能定位漏掉 recover 的位置
ctx.Status() 或 ctx.JSON() 后还调 ctx.Next(),后续逻辑全丢
一旦调用 ctx.Status()、ctx.SendString()、ctx.JSON() 等写响应的方法,Fiber 内部标记该 ctx 为 “committed”,再调 ctx.Next() 就被静默忽略。
- 典型翻车:权限中间件里写了
c.Status(401).JSON(...),接着又写c.Next(),以为能继续走日志或监控——实际后续所有中间件都不会执行 - 正确做法:拒绝请求就
return,放行才调c.Next();别在已写响应后尝试“继续流程” - 验证方式:用
curl -v http://localhost:3000/xxx看响应状态码和 body 是否符合预期,若状态码对但 body 空,大概率是中间件提前 return 了却没给响应
/metrics 或 /debug/pprof 返回 404,其实是路由被吞了
prom.Handler() 或 pprof.New() 必须在任何通配路由(如 app.All("/*", ...))和静态路由(如 app.Static())之前注册,否则这些路由会优先匹配 /metrics 或 /debug/pprof,导致指标采集失效。
- 错误顺序:
app.All("/*", fallbackHandler)在app.Use(prom.Handler())之前 →/metrics永远 404 - 临时验证:把
app.Get("/metrics", ...)改成app.Get("/debug/metrics", ...),绕过通配规则,确认指标能出来 - 必须检查的三件事:
curl -v http://localhost:3000/metrics返回 200、Content-Type: text/plain; version=0.0.4、日志里没有GET /metrics 404
NotFound 页面不生效,多半是配置时机或状态码漏了
NotFound 处理器只能在 fiber.New() 初始化时通过 fiber.Config{NotFound: ...} 传入,运行时修改 app.Config().NotFound = ... 完全无效;而且 handler 内必须显式调用 c.Status(404),否则浏览器收到的是 200。
- 错误写法:
app := fiber.New(); app.Config().NotFound = func(c *fiber.Ctx) error { ... }—— 不生效 - 正确写法:
app := fiber.New(fiber.Config{NotFound: my404Handler}) - 常见遗漏:
c.Render("404", nil)前没写c.Status(404),或者模板路径错(如./views/404.html实际不存在)导致 panic 后返回空白 - StrictRouting 开启时,
/users和/users/是两个不同路径,后者没注册就会直接进 NotFound —— 别关 StrictRouting,而是显式注册两个路由或加重定向
最常被忽略的一点:Fiber 不会帮你判断“该不该写响应”,它只忠实地执行你写的代码。所以排查核心永远是——看哪一行之后响应就发出去了,以及那行之前有没有别的中间件已经 commit 了 ctx。


















