crowdsecurity/crowdsec · error
unable to read logs from service %s: %w
Error message
unable to read logs from service %s: %w
What it means
tailServiceAttempt opens a swarm service log stream with d.Client.ServiceLogs(ctx, service.ID, logOptions). If that API call fails, it wraps as "unable to read logs from service %s". It means the docker API refused the ServiceLogs request for the configured swarm service.
Source
Thrown at pkg/acquisition/modules/docker/run.go:751
}
}
func (d *Source) tailServiceAttempt(ctx context.Context, service *ContainerConfig, outChan chan pipeline.Event, bo backoff.BackOff) error {
// For services, we need to get the service logs using the service logs API
// Docker service logs aggregates logs from all running tasks of the service
logOptions := client.ServiceLogsOptions{
ShowStdout: service.logOptions.ShowStdout,
ShowStderr: service.logOptions.ShowStderr,
Since: service.logOptions.Since,
Until: service.logOptions.Until,
Timestamps: service.logOptions.Timestamps,
Follow: service.logOptions.Follow,
Tail: service.logOptions.Tail,
Details: service.logOptions.Details,
}
dockerReader, err := d.Client.ServiceLogs(ctx, service.ID, logOptions)
if err != nil {
return fmt.Errorf("unable to read logs from service %s: %w", service.Name, err)
}
// Log connection (both initial and reconnections)
service.logger.Info("connected to service logs")
bo.Reset()
// Service logs don't use TTY, so we always use the dlog reader
reader := dlog.NewReader(dockerReader)
scanner := bufio.NewScanner(reader)
readerChan := make(chan string)
readerTomb := &tomb.Tomb{}
readerTomb.Go(func() error {
return ReadTailScanner(scanner, readerChan, readerTomb)
})
for {View on GitHub (pinned to 909b515798)
Solutions
- Ensure the configured docker_host is a swarm manager node: `docker service ls` must work with the same credentials/socket.
- Verify the service name/ID is current (`docker service ps <name>`); service IDs change on redeploys.
- With docker-socket-proxy, whitelist /services and /services/{id}/logs.
- Rely on the retry backoff — the attempt loop will re-resolve the service and reconnect.
Example fix
// before docker_host: unix:///var/run/docker.sock # on a worker node // after — point at a manager node docker_host: tcp://manager:2377
Defensive patterns
Strategy: retry
Validate before calling
// Go: confirm manager access and service existence first
services, err := cli.ServiceList(ctx, service.ListOptions{})
if err != nil {
return fmt.Errorf("not a swarm manager or daemon unreachable: %w", err)
}
for _, s := range services {
if s.Spec.Name == targetService {
return s.ID, nil
}
}
return "", fmt.Errorf("service %q not found", targetService) Try / catch
err := d.tailServiceAttempt(ctx, service, outChan, bo)
if err != nil && strings.Contains(err.Error(), "unable to read logs from service") {
time.Sleep(bo.NextBackOff())
// retry, re-resolving service ID
} Prevention
- Point docker_host at a swarm manager, not a worker.
- Resolve services by stable name, not ephemeral ID.
- Whitelist /services endpoints behind docker-socket-proxy.
- Verify `docker service ls` works with the same credentials before deploying.
When it happens
Trigger: ServiceLogs called for a service ID that no longer exists (service removed/updated between discovery and tail), the node is not a swarm manager (ServiceLogs requires manager access), or the daemon/proxy rejects the /services/{id}/logs endpoint.
Common situations: Pointing the docker datasource at a worker node's socket instead of a manager; service redeployed with a new ID; docker-socket-proxy blocking /services routes; swarm mode left after `docker swarm leave`.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- unable to read logs from container %s: %w
- no container found named: %s, can't run one shot acquisition
- reader connection lost for container %s
- reader connection lost for service %s
- appsec datasource requires a hub. this is a bug, please repo
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/c011212fc4d80496.
Report an issue: GitHub.