ipfs/kubo · error
serveHTTPGateway: %w
Error message
serveHTTPGateway: %w
What it means
While waiting for all gateway listeners to become ready, serveHTTPGateway selects on each ready channel; if any serving goroutine pushes an error into errc, startup fails fast with this wrapped error. The inner error is whatever made one of the gateway HTTP servers fail (listener accept error, TLS setup, handler panic recovery, node shutdown).
Source
Thrown at cmd/ipfs/kubo/daemon.go:1160
// This prevents race conditions where external tools (like systemd path units)
// see the file and try to connect before servers can accept connections.
if len(listeners) > 0 {
readyChannels := make([]chan struct{}, len(listeners))
for i, lis := range listeners {
readyChannels[i] = make(chan struct{})
ready := readyChannels[i]
wg.Go(func() {
errc <- corehttp.ServeWithReady(node, manet.NetListener(lis), ready, opts...)
})
}
// Wait for all listeners to be ready or any to fail
for _, ready := range readyChannels {
select {
case <-ready:
// This listener is ready
case err := <-errc:
return nil, fmt.Errorf("serveHTTPGateway: %w", err)
}
}
addr, err := manet.ToNetAddr(rewriteMaddrToUseLocalhostIfItsAny(listeners[0].Multiaddr()))
if err != nil {
return nil, fmt.Errorf("serveHTTPGateway: manet.ToNetAddr() failed: %w", err)
}
if err := node.Repo.SetGatewayAddr(addr); err != nil {
return nil, fmt.Errorf("serveHTTPGateway: SetGatewayAddr() failed: %w", err)
}
}
go func() {
wg.Wait()
close(errc)
}()
return errc, nilView on GitHub (pinned to 329838acdf)
Solutions
- Read the wrapped inner error in the message; it names the actual failing listener/server.
- Verify all Addresses.Gateway entries are bindable and not shut down by another component (e.g., check that no unit is stopping the daemon concurrently).
- If using socket activation, confirm the FD remains open and valid through startup.
- Reduce to a single known-good gateway address to isolate which listener fails, then fix that address.
Example fix
// before: diagnose which listener "serveHTTPGateway: accept tcp 0.0.0.0:8080: use of closed network connection" // after: stop the competing closer $ systemctl stop ipfs-gateway-socket-old && ipfs daemon
Defensive patterns
Strategy: try-catch
Try / catch
errc, err := serveHTTPGateway(req, cctx)
if err != nil {
var inner error
if errors.As(err, &inner) || errors.Unwrap(err) != nil {
log.Printf("gateway listener failed: %v", errors.Unwrap(err))
}
return err // fail startup; do not serve partially
} Prevention
- Keep all Addresses.Gateway entries bindable (validate each before start).
- Do not shutdown the daemon concurrently with startup scripts.
- With socket activation, verify FDs stay open through the whole boot sequence.
- Read the wrapped inner error; it names the failing listener.
When it happens
Trigger: One of the per-listener go routines in errc reports before all readyChannels fire: the underlying net.Listener was closed, Serve returned early (e.g., http.Server error), or the node shut down during startup.
Common situations: Multiple gateway addresses configured where one fails at serve time; systemd socket FD closed between TakeListeners and Serve; startup racing with `ipfs shutdown`; TLS listener misconfiguration.
Related errors
- serveHTTPGateway: GetConfig() failed: %s
- could not read config: %w
- serveHTTPGateway: socket activation failed: %s
- serveHTTPGateway: invalid gateway address: %q (err: %s)
- serveHTTPGateway: manet.Listen(%s) failed: %s
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/3c783f7c4f1e30dc.
Report an issue: GitHub.