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
- Inspect the wrapped cause — for bind problems it is usually 'address already in use'.
- Free the port: find the process with `ss -ltnp | grep <port>` and stop it, or change api.listen_uri.
- Binding <1024 without privileges: change to an unprivileged port or grant capabilities.
- 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
- Use a systemd Restart=on-failure policy for crowdsec.
- Avoid double-starting crowdsec (systemd + manual run).
- Monitor the LAPI port with a health check.
- Keep listen_uri on an unprivileged port in containers.
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
- while waiting on httpServerTomb: %w
- appsec datasource requires a hub. this is a bug, please repo
- appsec datasource requires a lapi client configuration. this
- missing lapi client credentials
- kubernetes client is not initialized
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/de4759578434568f.
Report an issue: GitHub.