crowdsecurity/crowdsec · critical

docker events connection failed: %w

Error message

docker events connection failed: %w

What it means

trySubscribeEvents calls d.Client.Events(ctx, opts) and checks the error channel non-blockingly for an immediate failure. If the docker daemon/socket is unreachable or the Events stream is rejected right away, the error is wrapped as "docker events connection failed". It signals the initial subscription to the docker event stream failed, not a mid-stream error.

Source

Thrown at pkg/acquisition/modules/docker/run.go:370

func (d *Source) trySubscribeEvents(ctx context.Context) (*subscription, error) {
	filters := client.Filters{
		"type": {
			"container": true,
			"service":   d.isSwarmManager,
		},
	}

	opts := client.EventsListOptions{
		Filters: filters,
	}

	result := d.Client.Events(ctx, opts)

	// Is there an immediate error (proxy/daemon unavailable) ?
	select {
	case err := <-result.Err:
		if err != nil {
			return nil, fmt.Errorf("docker events connection failed: %w", err)
		}
	default:
	}

	return &subscription{events: result.Messages, errs: result.Err}, nil
}

// subscribeEvents will loop until it can successfully call d.Client.Events()
// without immediately receiving an error. It applies exponential backoff on failures.
// Returns the new (eventsChan, errChan) pair or an error if context/tomb is done.
func (d *Source) subscribeEvents(ctx context.Context) (*subscription, error) {
	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	case <-d.t.Dying():
		return nil, errors.New("connection aborted, shutting down docker watcher")
	default:
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Check the daemon is reachable: `docker events --since 1s` on the same host/socket; fix DOCKER_HOST or the socket path in the docker datasource config.
  2. Fix permissions: add the crowdsec user to the docker group or adjust socket ACLs.
  3. If behind docker-socket-proxy, whitelist the /events (and containers) endpoints.
  4. Restart crowdsec once the daemon is up — the source retries subscription on the next manager loop.

Example fix

// before (acquis.yaml)
source: docker
// no docker_host, daemon not reachable
// after — point at a working daemon/socket
source: docker
docker_host: unix:///var/run/docker.sock
Defensive patterns

Strategy: retry

Validate before calling

// Go, before starting the source
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
if _, err := cli.Ping(ctx); err != nil {
	return fmt.Errorf("docker daemon unreachable: %w", err)
}

Try / catch

sub, err := trySubscribeEvents(ctx)
if err != nil && strings.Contains(err.Error(), "docker events connection failed") {
	// exponential backoff, resubscribe once daemon is back
	time.Sleep(backoff.Next())
	goto retry
}

Prevention

When it happens

Trigger: Calling the docker datasource startup (live mode, container discovery via events) when the docker daemon is down, the docker socket path is wrong, the user lacks permission on /var/run/docker.sock, or a docker-socket-proxy rejects the /events endpoint.

Common situations: CrowdSec started in a container without mounting /var/run/docker.sock; DOCKER_HOST pointing to a dead daemon; socket-proxy config missing GET /events in the allowed API; docker restarted while the source subscribes at boot.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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