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, nil

View on GitHub (pinned to 329838acdf)

Solutions

  1. Read the wrapped inner error in the message; it names the actual failing listener/server.
  2. 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).
  3. If using socket activation, confirm the FD remains open and valid through startup.
  4. 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

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


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/3c783f7c4f1e30dc. Report an issue: GitHub.