gofiber/fiber · critical
failed to listen
Error message
failed to listen: %w
What it means
Returned by App.Listen when app.createListener fails to bind the configured address. createListener wraps the underlying net.Listen / tls.Listen error as 'failed to listen', and Listen re-wraps it identically (listen.go:281/481), so the surfaced message is 'failed to listen: <net error>'. This is a socket-bind failure at server startup, before Serve runs.
Solutions
- Free the port: find and stop the holder (ss -ltnp / lsof -i :PORT) or pick a different port.
- For privileged ports, grant CAP_NET_BIND_SERVICE or run on :8080 behind a reverse proxy.
- For unix sockets, ensure the parent directory exists and is writable and set UnixSocketFileMode appropriately.
- Add SO_REUSEADDR via a custom listener / startup retry-with-backoff for the restart race, and fail fast with a clear log.
Example fix
// before
app.Listen(":80") // permission denied for non-root
// after
app.Listen(":8080") // or grant CAP_NET_BIND_SERVICE to the binary Defensive patterns
Strategy: retry
Validate before calling
// preflight: is the address free before Listen?
ln, err := net.Listen("tcp", addr)
if err != nil {
log.Fatalf("address %s unavailable: %v", addr, err)
}
_ = ln.Close() Type guard
null
Try / catch
err := app.Listen(addr)
if err != nil {
if strings.Contains(err.Error(), "failed to listen") {
// bind failure: port taken, permission denied, bad addr
log.Fatalf("cannot bind %s: %v", addr, err)
}
log.Fatal(err)
} Prevention
- Check the port is free (ss -ltnp / lsof) before starting, especially after a crash.
- Avoid privileged ports (<1024) for non-root processes; use CAP_NET_BIND_SERVICE or :8080.
- For unix sockets, ensure the parent dir exists and is writable; set UnixSocketFileMode.
- Add bounded startup retry-with-backoff to survive the restart race for the same port.
When it happens
Trigger: Calling app.Listen(":3000") when the port is already taken; binding to a privileged port (<1024) as a non-root user; an invalid/malformed address; a unix socket path whose directory is not writable; or TLS Listen with a bad tls.Config.
Common situations: Another process (or a previous instance that did not release the port) holds the address; Docker host-network or port-publishing conflicts; binding to 0.0.0.0 when only loopback is permitted; unix-socket mode where /run/app dir is missing or has wrong perms; systemd unit restarting before the old socket closes.
Related errors
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/b0aee3579d52d271.
Report an issue: GitHub.
Appendix: source
Thrown at listen.go:283
}
// Graceful shutdown
if cfg.GracefulContext != nil {
ctx, cancel := context.WithCancel(cfg.GracefulContext)
defer cancel()
go app.gracefulShutdown(ctx, &cfg)
}
// Start prefork
if cfg.EnablePrefork {
return app.prefork(addr, tlsConfig, &cfg)
}
// Configure Listener
ln, err := app.createListener(addr, tlsConfig, &cfg)
if err != nil {
return fmt.Errorf("failed to listen: %w", err)
}
// Close the listener on any path that doesn't reach Serve (which otherwise
// takes ownership of it) — an early error return or a panicking hook — so
// the bound socket isn't leaked.
served := false
defer func() {
if !served {
_ = ln.Close() //nolint:errcheck // best-effort cleanup on the error path
}
}()
// prepare the server for the start
app.startupProcess()
listenData := app.prepareListenData(ln.Addr().String(), getTLSConfig(ln) != nil, &cfg, nil)
// run hooksView on GitHub (pinned to a105acad6c)