Как работает обработка ошибок в Fiber? Что такое custom error handler?
Возвращайте ошибки из обработчиков через return err или fiber.NewError(status, msg). Кастомный error handler задаётся в fiber.Config{ErrorHandler: fn} и централизованно управляет форматом всех HTTP-ошибок. Используйте errors.As для типизированной обработки.
Обработка ошибок в Fiber
Fiber использует единую точку обработки ошибок — error handler. Любой обработчик или middleware может вернуть ошибку через return err, и Fiber передаст её в зарегистрированный error handler. Это позволяет централизовать логирование, форматирование и коды ответов.
Встроенный механизм
По умолчанию Fiber обрабатывает ошибки типа *fiber.Error и стандартные ошибки Go. Если вернуть обычную ошибку — статус будет 500. Для HTTP-ошибок используйте fiber.NewError(statusCode, message):
app.Get("/users/:id", func(c *fiber.Ctx) error {
id, err := c.ParamsInt("id")
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "id must be integer")
}
if id == 0 {
return fiber.ErrNotFound // предустановленная ошибка 404
}
return c.JSON(fiber.Map{"id": id})
})
Кастомный Error Handler
Кастомный error handler задаётся в fiber.Config при создании приложения. Он получает *fiber.Ctx и error, и должен сформировать финальный ответ клиенту:
package main
import (
"errors"
"log"
"github.com/gofiber/fiber/v2"
)
// Кастомный тип ошибки
type AppError struct {
Code int `json:"code"`
Message string `json:"message"`
Details string `json:"details,omitempty"`
}
func (e *AppError) Error() string {
return e.Message
}
func customErrorHandler(c *fiber.Ctx, err error) error {
// Определяем HTTP-статус
code := fiber.StatusInternalServerError
msg := "internal server error"
details := ""
// fiber.Error — HTTP-ошибка с явным статусом
var fiberErr *fiber.Error
if errors.As(err, &fiberErr) {
code = fiberErr.Code
msg = fiberErr.Message
}
// AppError — доменная ошибка приложения
var appErr *AppError
if errors.As(err, &appErr) {
code = appErr.Code
msg = appErr.Message
details = appErr.Details
}
// Логируем 5xx
if code >= 500 {
log.Printf("ERROR [%s %s]: %v", c.Method(), c.Path(), err)
}
// Устанавливаем Content-Type явно
c.Set(fiber.HeaderContentType, fiber.MIMEApplicationJSONCharsetUTF8)
return c.Status(code).JSON(fiber.Map{
"error": msg,
"details": details,
"path": c.Path(),
})
}
func main() {
app := fiber.New(fiber.Config{
ErrorHandler: customErrorHandler,
})
app.Get("/ok", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"status": "ok"})
})
app.Get("/fail", func(c *fiber.Ctx) error {
return &AppError{Code: 422, Message: "validation failed", Details: "field 'name' is required"}
})
app.Get("/crash", func(c *fiber.Ctx) error {
return errors.New("unexpected database error")
})
log.Fatal(app.Listen(":3000"))
}
Предустановленные ошибки Fiber
fiber.ErrBadRequest // 400
fiber.ErrUnauthorized // 401
fiber.ErrForbidden // 403
fiber.ErrNotFound // 404
fiber.ErrMethodNotAllowed // 405
fiber.ErrRequestEntityTooLarge // 413
fiber.ErrUnprocessableEntity // 422
fiber.ErrTooManyRequests // 429
fiber.ErrInternalServerError // 500
fiber.ErrServiceUnavailable // 503
Совместная работа с middleware recover
Middleware recover перехватывает паники и конвертирует их в вызов error handler с ошибкой 500. Убедитесь, что recover зарегистрирован первым:
import "github.com/gofiber/fiber/v2/middleware/recover"
app.Use(recover.New(recover.Config{
EnableStackTrace: true,
}))
// Другие middleware после recover...
Подводные камни
- Возврат nil после c.JSON: Если в обработчике не вернуть ошибку (
return nil), но до этого уже вызватьc.JSON, ответ будет отправлен. Двойной вызов записи в ответ приведёт к ошибке fasthttp. Всегда используйтеreturn c.JSON(...). - Error handler не вызывается для app.Use без Next: Если middleware вернул ошибку через
return err, ноc.Next()не был вызван, error handler всё равно сработает. Но если middleware отправил ответ и вернул nil — error handler не вызовется даже при логической ошибке. - errors.As vs прямое приведение: Используйте
errors.Asвместо type assertion — это корректно работает с цепочками ошибок (wrapping черезfmt.Errorf("%w", err)). - Статус 200 при ошибке: Если в error handler забыть вызвать
c.Status(code)перед JSON — ответ уйдёт со статусом 200, несмотря на тело ошибки. - Повторная запись заголовков: После того как ответ начал отправляться (headers committed), нельзя изменить статус. Убедитесь, что error handler вызывается до любой отправки данных.
- Goroutine и ошибки: Ошибки из горутин, запущенных внутри обработчика, не попадают в error handler автоматически. Их нужно перехватывать вручную через каналы или recover внутри горутины.
- Паника в error handler: Если в самом error handler произойдёт паника — middleware recover её не поймает (он уже отработал). Пишите error handler максимально оборонительно.
Common mistakes
- Давать ответ про обработка ошибок в Fiber только на уровне определения, не показывая поведение в реальном приложении.
- Игнорировать границы ответственности вокруг темы «обработка ошибок в Fiber»: кто отменяет работу, кто владеет ресурсом и где формируется ответ клиенту.
- Не связывать обработка ошибок в Fiber с observability, тестированием или безопасностью, когда это влияет на продакшен-поведение.
What the interviewer is testing
- Точно объясняет, что именно делает обработка ошибок в Fiber и где это используется в Go-коде.
- Связывает обработка ошибок в Fiber с корректным lifecycle запроса, отменой, конкурентностью или конфигурацией сервера там, где это уместно.
- Не изобретает API и опирается на реальные контракты официальной документации.