charmbracelet/crush · error
server error: %v
Error message
server error: %v
What it means
The `server` command runs an HTTP server and watches an error channel. When any goroutine pushes a non-nil error that is not http.ErrServerClosed, the command closes the server and returns this wrapped error, causing the CLI to exit non-zero. It is the top-level propagation point for any runtime failure inside the server loop.
Source
Thrown at internal/cmd/server.go:79
errch := make(chan error, 1)
sigch := make(chan os.Signal, 1)
sigs := []os.Signal{os.Interrupt}
sigs = append(sigs, addSignals(sigs)...)
signal.Notify(sigch, sigs...)
go func() {
errch <- srv.ListenAndServe()
}()
select {
case <-sigch:
slog.Info("Received interrupt signal...")
case err = <-errch:
if err != nil && !errors.Is(err, server.ErrServerClosed) {
_ = srv.Close()
slog.Error("Server error", "error", err)
return fmt.Errorf("server error: %v", err)
}
}
if errors.Is(err, server.ErrServerClosed) {
return nil
}
ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)
defer cancel()
slog.Info("Shutting down...")
if err := srv.Shutdown(ctx); err != nil {
slog.Error("Failed to shutdown server", "error", err)
return fmt.Errorf("failed to shutdown server: %v", err)
}
return nilView on GitHub (pinned to 7944b8e522)
Solutions
- Check that the configured listen address/port is free (lsof -i :PORT or ss -ltnp) and stop the conflicting process or change the port
- Run the command with sufficient privileges or use a port >=1024 if binding a privileged port
- Inspect the 'Server error' slog line printed just before this error for the root cause
- If shutting down intentionally, ensure only ErrServerClosed is sent or filtered correctly
Example fix
// before
return fmt.Errorf("server error: %v", err)
// after
return fmt.Errorf("server error: %w", err) // preserve wrap for errors.Is checks downstream Defensive patterns
Strategy: try-catch
Validate before calling
// before starting the server
if l, err := net.Listen("tcp", addr); err != nil {
return fmt.Errorf("address %s unavailable: %w", addr, err)
} else {
l.Close()
} Try / catch
if err := runServer(ctx); err != nil {
if errors.Is(err, server.ErrServerClosed) {
return nil // intentional shutdown
}
slog.Error("Server failed", "error", err)
os.Exit(1)
} Prevention
- Probe the listen address with net.Listen before starting
- Run services on unprivileged ports >=1024
- Always compare with errors.Is(err, server.ErrServerClosed) instead of == so wrapped errors match
- Use %w not %v when wrapping so callers can inspect causes
When it happens
Trigger: Any error sent on errch (e.g. http.Server Serve/ListenAndServe failing: port already in use, permission denied on socket, TLS cert issues) that is not server.ErrServerClosed.
Common situations: Port 8080 (or configured port) already bound by another process; running without privileges on a low port; interface/address misconfiguration; TLS certificate files missing or invalid.
Related errors
- failed to shutdown server: %v
- empty providers list from catwalk
- failed to make request: %w
- failed to read response: %w
- cannot continue an agent tool session: %s
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/84a8a1ef13093717.
Report an issue: GitHub.