valyala/fasthttp · warning
prefork: close inherited listener fd: %w
Error message
prefork: close inherited listener fd: %w
What it means
In fasthttp's prefork child process (listen called from listenAsChild), the inherited listener FD is wrapped via os.NewFile and converted with net.FileListener; the wrapping *os.File is then closed to avoid leaking the original descriptor. If that Close fails, the error is wrapped as 'prefork: close inherited listener fd'. The listener itself owns a dup'd fd and remains usable; this signals an fd bookkeeping problem in the child process.
Source
Thrown at prefork/prefork.go:274
if p.Network == "" {
p.Network = defaultNetwork
}
if p.Reuseport {
return reuseport.Listen(p.Network, addr)
}
// fd inheritedListenerFD is the first ExtraFiles entry passed by the
// master process when Reuseport is false. Naming the file gives clearer
// errors from net.FileListener if the fd is invalid.
//
// net.FileListener dups the fd, so we close the wrapping *os.File after
// it returns to avoid leaking the original descriptor. The returned
// listener owns its own dup'd fd and is unaffected by this close.
f := os.NewFile(inheritedListenerFD, "fasthttp-prefork-listener")
ln, err := net.FileListener(f)
if closeErr := f.Close(); closeErr != nil && err == nil {
err = fmt.Errorf("prefork: close inherited listener fd: %w", closeErr)
}
if err != nil {
if ln != nil {
_ = ln.Close()
}
return nil, err
}
return ln, nil
}
// listenAsChild performs the common child process setup: creates the listener
// and starts watching the master process if OnMasterDeath is configured.
func (p *Prefork) listenAsChild(addr string) (net.Listener, error) {
ln, err := p.listen(addr)
if err != nil {
return nil, err
}
View on GitHub (pinned to c96f600972)
Solutions
- Update fasthttp — recent versions hardened this path; verify you are on a current release.
- Check the environment: run without sandbox/restrictions or adjust seccomp profiles to allow standard fd syscalls.
- Ensure nothing else closes or reuses the inherited listener FD before prefork's listen runs.
- As a fallback, disable prefork if your deployment doesn't need multi-process socket sharing.
Example fix
// before
// prefork enabled inside a restricted sandbox
panic(fasthttp.Prefork(serv, handler))
// after
if os.Getenv("SANDBOXED") == "1" {
// skip prefork in restricted environments
panic(fasthttp.Serve(ln, handler))
} Defensive patterns
Strategy: fallback
Validate before calling
// Before enabling prefork in constrained environments, verify fd ops work:
f := os.NewFile(3, "probe")
if f != nil {
if err := f.Close(); err != nil {
log.Printf("fd close unavailable in this sandbox: %v", err)
}
} Type guard
func preforkSupported() bool {
return runtime.GOOS != "windows" && os.Getenv("SANDBOXED") != "1"
} Try / catch
// top-level:
if err := run(); err != nil {
if strings.Contains(err.Error(), "close inherited listener fd") {
log.Printf("prefork fd issue, falling back to single process: %v", err)
return serveWithoutPrefork()
}
return err
} Prevention
- Pin recent fasthttp versions where prefork fd handling is hardened.
- Test prefork under your actual sandbox/seccomp profile before deploying.
- Never close or dup the inherited listener FD yourself before prefork runs.
- Disable prefork where multi-process socket sharing isn't required.
When it happens
Trigger: Running with prefork enabled and the child calling f.Close() on the inherited listener file after net.FileListener — Close fails e.g. due to an invalid fd, fd already closed, or sandbox environments restricting fd operations.
Common situations: Containers/sandboxes (gVisor, restricted seccomp) where close(2) on inherited fds misbehaves; running prefork under supervisors that pass unexpected fd state; custom code touching the inherited FD before prefork listens.
Related errors
- prefork: resolve %s/%s: %w
- prefork: dup listener fd: %w
- fasthttp: no args value for the given key
- fasthttp: pipelined requests' queue has been overflowed. inc
- pipeline connection has been stopped
AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31).
Data as JSON: /api/errors/14309e9bde0184ee.
Report an issue: GitHub.