github/github-mcp-server · critical

HTTP server error: %w

Error message

HTTP server error: %w

What it means

httpSvr.ListenAndServe returned an error other than http.ErrServerClosed - the listener could not serve. The overwhelmingly common cause is the listen address being unavailable: port already in use (EADDRINUSE), permission denied on a privileged port, or the address not being assignable on this host.

Source

Thrown at pkg/http/server.go:229

	go func() {
		<-ctx.Done()
		shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		logger.Info("shutting down server")
		if err := httpSvr.Shutdown(shutdownCtx); err != nil {
			logger.Error("error during server shutdown", "error", err)
		}
	}()

	if cfg.ExportTranslations {
		// Once server is initialized, all translations are loaded
		dumpTranslations()
	}

	logger.Info("HTTP server listening", "addr", addr)
	if err := httpSvr.ListenAndServe(); err != nil && err != http.ErrServerClosed {
		return fmt.Errorf("HTTP server error: %w", err)
	}

	logger.Info("server stopped gracefully")
	return nil
}

// resolveListenAddress returns the address string passed to http.Server.
// When host is empty the server binds to all interfaces on the given port;
// otherwise host and port are joined into a single address.
func resolveListenAddress(host string, port int) string {
	if host == "" {
		return fmt.Sprintf(":%d", port)
	}
	return net.JoinHostPort(host, strconv.Itoa(port))
}

func initGlobalToolScopeMap(t translations.TranslationHelperFunc, hostType utils.HostType) error {
	// Build inventory with all tools to extract scope information

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Find and stop the process holding the port (ss -ltnp / lsof -i :PORT) or change the port
  2. Use an unprivileged port (>1024) or grant CAP_NET_BIND_SERVICE
  3. Check the logged 'HTTP server listening' address matches the intended interface

Example fix

// before
port := 80

// after
port := 8080 // unprivileged; map 80->8080 at the load balancer/container level
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: verify the address is bindable before full startup
ln, err := net.Listen("tcp", resolveListenAddress(cfg.Host, cfg.Port))
if err != nil {
	return fmt.Errorf("address in use: %w", err)
}
_ = ln.Close()

Try / catch

if err := httpSvr.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
	if errors.Is(err, syscall.EADDRINUSE) {
		// port collision: fail fast with an actionable message
		return fmt.Errorf("port %d already in use: %w", cfg.Port, err)
	}
	return fmt.Errorf("HTTP server error: %w", err)
}

Prevention

When it happens

Trigger: Another process (or a second instance of this server) already bound the configured host:port; binding a port below 1024 as non-root; container port conflicts; stale process from a previous run.

Common situations: Running two copies of the server locally; port collisions in docker-compose/Kubernetes; switching to port 80/443 without CAP_NET_BIND_SERVICE.

Related errors


AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15). Data as JSON: /api/errors/aa81da1d4e27e892. Report an issue: GitHub.