crowdsecurity/crowdsec · error

local API server stopped with error: %w

Error message

local API server stopped with error: %w

What it means

APIServer.Run returns this when the tomb-wrapped listenAndServeLAPI goroutine exits with an error after Wait() — i.e. the local API server crashed or failed while serving. It aggregates failures from the HTTP listener lifecycle (including error 604).

Source

Thrown at pkg/apiserver/apiserver.go:358

		Handler:   s.router,
		TLSConfig: tlsCfg,
		Protocols: &http.Protocols{},
	}

	s.httpServer.Protocols.SetHTTP1(true)
	s.httpServer.Protocols.SetUnencryptedHTTP2(true)
	s.httpServer.Protocols.SetHTTP2(true)

	if s.apic != nil {
		s.initAPIC(ctx)
	}

	s.httpServerTomb.Go(func() error {
		return s.listenAndServeLAPI(ctx, apiReady)
	})

	if err := s.httpServerTomb.Wait(); err != nil {
		return fmt.Errorf("local API server stopped with error: %w", err)
	}

	return nil
}

// listenAndServeLAPI starts the http server and blocks until it's closed
// it also updates the URL field with the actual address the server is listening on
// it's meant to be run in a separate goroutine
func (s *APIServer) listenAndServeLAPI(ctx context.Context, apiReady chan bool) error {
	serverError := make(chan error, 2)

	listenConfig := &net.ListenConfig{}

	startServer := func(listener net.Listener, canTLS bool) {
		var err error

		if canTLS && s.cfg.TLS != nil && (s.cfg.TLS.CertFilePath != "" || s.cfg.TLS.KeyFilePath != "") {
			if s.cfg.TLS.KeyFilePath == "" {

View on GitHub (pinned to 909b515798)

Solutions

  1. Inspect the wrapped cause — for bind problems it is usually 'address already in use'.
  2. Free the port: find the process with `ss -ltnp | grep <port>` and stop it, or change api.listen_uri.
  3. Binding <1024 without privileges: change to an unprivileged port or grant capabilities.
  4. If transient, restart crowdsec; check journalctl for the full chain.

Example fix

// before
api:
  server:
    listen_uri: 127.0.0.1:8080
// after
api:
  server:
    listen_uri: 127.0.0.1:8081
Defensive patterns

Strategy: try-catch

Validate before calling

// before Run, ensure the port is free
if ln, err := net.Listen("tcp", cfg.ListenURI); err != nil {
    return fmt.Errorf("LAPI address %s unavailable: %w", cfg.ListenURI, err)
} else {
    ln.Close()
}

Try / catch

if err := apiServer.Run(ctx, ready); err != nil {
    log.Errorf("LAPI stopped: %v", err) // inspect wrapped cause
    // restart with backoff if the cause is transient
}

Prevention

When it happens

Trigger: Run called and the internal HTTP server fails: listener creation error, accept loop failure, or shutdown error propagated from listenAndServeLAPI.

Common situations: Port already in use, bind permission denied on a privileged port, listener socket closed unexpectedly mid-run.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/de4759578434568f. Report an issue: GitHub.