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 informationView on GitHub (pinned to 0ea1f775a7)
Solutions
- Find and stop the process holding the port (ss -ltnp / lsof -i :PORT) or change the port
- Use an unprivileged port (>1024) or grant CAP_NET_BIND_SERVICE
- 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
- Check for listeners on the port before starting a second instance
- Use unprivileged ports and map them at the edge
- Rely on graceful shutdown signals so old instances release ports promptly
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
- starting callback listener on %s: %w
- failed to unmarshal toolsets: %w
- failed to unmarshal tools: %w
- failed to build inventory: %w
- private key is %T, want an RSA key
AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15).
Data as JSON: /api/errors/aa81da1d4e27e892.
Report an issue: GitHub.