gofiber/fiber · error
shutdown: graceful timeout has been reached, exiting
Error message
shutdown: graceful timeout has been reached, exiting
What it means
ErrGracefulTimeout is a public sentinel declared at error.go:16 that signals a graceful shutdown exceeded its deadline. In this fiber/v3 checkout it has no internal callers: the shutdown path in listen.go drives app.ShutdownWithContext and surfaces context.DeadlineExceeded instead. The sentinel exists as part of the public API so that callers comparing against it (or future revisions that return it) get a stable value to match with errors.Is.
Solutions
- If you depend on this exact value, match with errors.Is(err, fiber.ErrGracefulTimeout) so your code keeps working if a future revision returns it.
- To stop the timeout firing, raise the shutdown deadline passed to ShutdownWithTimeout, or accelerate handler drain (close idle keep-alive connections, signal websocket peers to close).
- If you need to surface this sentinel from your own shutdown wrapper, wrap and return it explicitly when ctx.Err() != nil during ShutdownWithContext.
Example fix
// before
if err := app.ShutdownWithTimeout(5 * time.Second); err != nil {
log.Printf("shutdown failed: %v", err)
}
// after
if err := app.ShutdownWithTimeout(30 * time.Second); err != nil {
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, fiber.ErrGracefulTimeout) {
log.Printf("graceful shutdown timed out; forcing close")
} else {
log.Printf("shutdown failed: %v", err)
}
} Defensive patterns
Strategy: try-catch
Type guard
// isGracefulTimeout reports whether err represents a graceful-shutdown
// timeout. It matches both the public sentinel and context.DeadlineExceeded
// (the value the current revision actually returns from ShutdownWithContext).
func isGracefulTimeout(err error) bool {
return errors.Is(err, fiber.ErrGracefulTimeout) ||
errors.Is(err, context.DeadlineExceeded)
} Try / catch
if err := app.ShutdownWithTimeout(d); err != nil {
if isGracefulTimeout(err) {
log.Printf("graceful shutdown timed out; forcing close")
} else {
return err
}
} Prevention
- Match with errors.Is so the code keeps working when the returned sentinel changes.
- Right-size the shutdown deadline for the slowest handler (websockets, uploads).
- Signal long-lived connections to close before initiating shutdown.
When it happens
Trigger: The error would be returned by a Shutdown variant once graceful draining of in-flight connections exceeds the supplied timeout. In the current revision, callers see context.DeadlineExceeded from the context passed to ShutdownWithContext; matching ErrGracefulTimeout returns false unless the application wraps and returns it itself.
Common situations: Long-running handlers (websockets, slow uploads, streaming responses) that keep connections alive past the shutdown deadline; test harnesses that assert on a specific graceful-timeout error and find a context error instead; version upgrades where the returned sentinel changes.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- shutdown: server is not running
- cache: failed to delete key
- cache: failed to get key
- cache: failed to get raw key
- cache: failed to store key
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/295a3bcb29f14487.
Report an issue: GitHub.
Appendix: source
Thrown at error.go:16
package fiber
import (
"encoding/json"
"errors"
"github.com/gofiber/schema"
)
// Wrap and return this for unreachable code if panicking is undesirable (i.e., in a handler).
// Unexported because users will hopefully never need to see it.
var errUnreachable = errors.New("fiber: unreachable code, please create an issue at github.com/gofiber/fiber")
// General errors
var (
ErrGracefulTimeout = errors.New("shutdown: graceful timeout has been reached, exiting")
// ErrNotRunning indicates that a Shutdown method was called when the server was not running.
ErrNotRunning = errors.New("shutdown: server is not running")
// ErrHandlerExited is returned by App.Test if a handler panics or calls runtime.Goexit().
ErrHandlerExited = errors.New("runtime.Goexit() called in handler or server panic")
// ErrNoViewEngineConfigured indicates that a helper requiring a view engine was invoked without one configured.
ErrNoViewEngineConfigured = errors.New("fiber: no view engine configured")
// ErrAutoCertWithCertFile indicates AutoCertManager cannot be used with CertFile/CertKeyFile.
ErrAutoCertWithCertFile = errors.New("tls: AutoCertManager cannot be combined with CertFile/CertKeyFile")
// ErrRouteNotRepresentable indicates a route whose path no relative URL can
// name, so Route.URL, GetRouteURL and Redirect().Route cannot compose one.
// A path starting with two or more slashes is such a route: the URL that
// would reach it opens an authority instead.
ErrRouteNotRepresentable = errors.New("router: route path cannot be expressed as a relative URL")
)
// Fiber redirection errors
var (
ErrRedirectBackNoFallback = NewError(StatusInternalServerError, "Referer not found, you have to enter fallback URL for redirection.")View on GitHub (pinned to a105acad6c)