gofiber/fiber · warning
shutdown: server is not running
Error message
shutdown: server is not running
What it means
ErrNotRunning is returned by App.ShutdownWithContext (app.go:1337) when app.server is nil, i.e. when a Shutdown variant is called before the server has been started by Listen or Listener. It is a benign precondition error: there is nothing to drain because no listener was ever bound.
Solutions
- Only call Shutdown after Listen has returned or after ConfirmStartup confirms the server is up.
- Treat ErrNotRunning as expected in cleanup paths: ignore it with errors.Is(err, fiber.ErrNotRunning).
- If you drive shutdown from a goroutine, gate it on a started channel that Listen signals once app.server is non-nil.
Example fix
// before
if err := app.ShutdownWithContext(ctx); err != nil {
return fmt.Errorf("shutdown: %w", err)
}
// after
if err := app.ShutdownWithContext(ctx); err != nil {
if errors.Is(err, fiber.ErrNotRunning) {
return nil // server was never started; nothing to do
}
return fmt.Errorf("shutdown: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
// Only shut down if the server has actually started. Track startup with a
// channel that Listen signals once app.server is non-nil.
var started = make(chan struct{})
go func() {
if err := app.Listen(":8080"); err != nil {
log.Fatal(err)
}
close(started)
}()
select {
case <-started:
_ = app.ShutdownWithContext(ctx)
case <-ctx.Done():
// never started; nothing to shut down
} Try / catch
if err := app.ShutdownWithContext(ctx); err != nil {
if errors.Is(err, fiber.ErrNotRunning) {
return nil // benign: server was never started
}
return fmt.Errorf("shutdown: %w", err)
} Prevention
- Treat ErrNotRunning as expected in signal handlers and test cleanup.
- Gate shutdown on a startup-confirmed signal so the SIGTERM handler cannot race the serve goroutine.
- In tests, only call Shutdown when the test actually started the server.
When it happens
Trigger: Calling app.Shutdown(), app.ShutdownWithTimeout(d), or app.ShutdownWithContext(ctx) before app.Listen(addr) (or Listener/ListenTLS/ListenMutualTLS) has been invoked. Also seen in test teardown when the test never started the server, and in graceful-shutdown signal handlers that fire before serve completes.
Common situations: Signal-handling shutdown wired up before the listen goroutine has assigned app.server; tests that construct an App for handler unit-tests and then call Shutdown in t.Cleanup; race between startup failure and the SIGTERM handler.
Related errors
- shutdown: graceful timeout has been reached, exiting
- context canceled while starting service
- errStreamClosed
- fiber: no view engine configured
- fiber: service is nil
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/057e54f229139ff6.
Report an issue: GitHub.
Appendix: source
Thrown at error.go:18
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)