Bug description
CrowdSec (container, v1.8.1) crashes with exit code 1 every time it receives SIGTERM while a source: docker acquisition is active: instead of a clean shutdown it panics with invalid memory address or nil pointer dereference inside the docker acquisition module, ~0.5 s after SIGTERM is received.
Observed 4/4 times in 18 h on a Docker homelab (4 SIGTERM events → 4 panics → exit 1). Because the container runs with restart: unless-stopped, each shutdown looks like a crash loop to operators, though the process runs fine for hours in between.
Expected behavior
docker stop crowdsec (or any SIGTERM) should shut down cleanly with exit code 0, like any other stop of the container.
Actual behavior
time="2026-09-07T22:00:15Z" level=warning msg="SIGTERM received, shutting down"
time="2026-09-07T22:00:15Z" level=info msg="killing tail for container miniflux" module=acquisition.docker type=docker
time="2026-09-07T22:00:16Z" level=error msg="crowdsec - goroutine crashed: runtime error: invalid memory address or nil pointer dereference"
time="2026-09-07T22:00:16Z" level=fatal msg="crowdsec stopped unexpectedly."
Full panic stack (goroutine 146):
sync/atomic.(*Int32).Add(...)
sync/atomic/type.go:94
sync.(*RWMutex).RLock(...)
sync/rwmutex.go:72
github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/docker/tracker.(*Tracker[...]).Get(...)
github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/docker/tracker/tracker.go:46 +0x22
github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/docker.(*Source).checkContainers(...)
github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/docker/run.go:327 +0x4f6
github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/docker.(*Source).Watch(...)
github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/docker/run.go:454 +0x653
github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/docker.(*Source).StreamingAcquisition(...)
github.com/crowdsecurity/crowdsec/pkg/acquisition/modules/docker/run.go:509 +0x23f
github.com/crowdsecurity/crowdsec/pkg/acquisition.acquireSource(...)
github.com/crowdsecurity/crowdsec/pkg/acquisition/acquisition.go:609 +0x112
github.com/crowdsecurity/crowdsec/pkg/acquisition.StartAcquisition.func1()
github.com/crowdsecurity/crowdsec/pkg/acquisition/acquisition.go:660 +0x470
Steps to reproduce
- Run
crowdsecurity/crowdsec:latest (v1.8.1) in Docker with a docker acquisition datasource, e.g.:
source: docker
docker_host: tcp://docker-socket-proxy:2375
container_name: [miniflux]
labels:
type: miniflux
program: miniflux
- Let it start and record logs ("Starting docker acquisition", "Starting tail").
- Send SIGTERM (
docker stop crowdsec or any compose fleet recreate that stops the container).
- Observe: panic +
level=fatal + exit code 1, every time.
Root cause analysis
The goroutine Watch (run.go:454) calls checkContainers (run.go:327), which does d.runningContainerState.Get(container.ID) → Tracker.Get (tracker.go:46) → RLock. During shutdown the acquisition source / tracker is torn down while this goroutine is still executing, so RLock dereferences freed/invalid state → nil pointer panic. This is a shutdown race in the docker acquisition module.
Additional observations
- Present on master too:
pkg/acquisition/modules/docker/tracker/tracker.go and pkg/acquisition/modules/docker/run.go are byte-identical between tag v1.8.1 and master (checked 2026-09-08). No fix upstream yet.
- Stacktrace is silently lost in the official image:
/var/lib/crowdsec/data/trace is a symlink to /staging/ inside the image, so the trace write fails with unable to write stacktrace: open /var/lib/crowdsec/data/trace/.... This makes the crash look like a silent termination. Full traces are only recoverable from the container logs (escaped \n).
Environment
- CrowdSec: v1.8.1-909b5157 (
alphaga, BuildDate 2026-09-03, Go 1.26.8, Platform: docker)
- Image:
crowdsecurity/crowdsec:latest (pulled 2026-09-04)
- Host: CachyOS Linux, Docker 29.7.2, containerd-snapshotter enabled
- Container user: 1031:972 (non-root)
- Acquisition:
source: docker (via tecnativa/docker-socket-proxy, CONTAINERS=1) + several source: file datasources
Bug description
CrowdSec (container, v1.8.1) crashes with exit code 1 every time it receives SIGTERM while a
source: dockeracquisition is active: instead of a clean shutdown it panics withinvalid memory address or nil pointer dereferenceinside the docker acquisition module, ~0.5 s after SIGTERM is received.Observed 4/4 times in 18 h on a Docker homelab (4 SIGTERM events → 4 panics → exit 1). Because the container runs with
restart: unless-stopped, each shutdown looks like a crash loop to operators, though the process runs fine for hours in between.Expected behavior
docker stop crowdsec(or any SIGTERM) should shut down cleanly with exit code 0, like any other stop of the container.Actual behavior
Full panic stack (goroutine 146):
Steps to reproduce
crowdsecurity/crowdsec:latest(v1.8.1) in Docker with a docker acquisition datasource, e.g.:docker stop crowdsecor any compose fleet recreate that stops the container).level=fatal+ exit code 1, every time.Root cause analysis
The goroutine
Watch(run.go:454) callscheckContainers(run.go:327), which doesd.runningContainerState.Get(container.ID)→Tracker.Get(tracker.go:46) →RLock. During shutdown the acquisition source / tracker is torn down while this goroutine is still executing, soRLockdereferences freed/invalid state → nil pointer panic. This is a shutdown race in the docker acquisition module.Additional observations
pkg/acquisition/modules/docker/tracker/tracker.goandpkg/acquisition/modules/docker/run.goare byte-identical between tag v1.8.1 and master (checked 2026-09-08). No fix upstream yet./var/lib/crowdsec/data/traceis a symlink to/staging/inside the image, so the trace write fails withunable to write stacktrace: open /var/lib/crowdsec/data/trace/.... This makes the crash look like a silent termination. Full traces are only recoverable from the container logs (escaped\n).Environment
alphaga, BuildDate 2026-09-03, Go 1.26.8, Platform: docker)crowdsecurity/crowdsec:latest(pulled 2026-09-04)source: docker(via tecnativa/docker-socket-proxy,CONTAINERS=1) + severalsource: filedatasources