crowdsecurity/crowdsec · error
unable to read logs from container %s: %w
Error message
unable to read logs from container %s: %w
What it means
tailContainerAttempt opens the container log stream with d.Client.ContainerLogs(ctx, container.ID, *container.logOptions). If that API call fails (daemon unreachable, container gone/removed, API rejected options), it wraps the error as "unable to read logs from container %s". It is the initial connection (or reconnection attempt, under backoff) to a container's logs failing.
Source
Thrown at pkg/acquisition/modules/docker/run.go:626
}
wait := bo.NextBackOff()
container.logger.Debugf("tail failed but container is (presumed) healthy: %v, retrying in %s", err, wait)
select {
case <-time.After(wait):
case <-container.t.Dying():
container.logger.Infof("tail stopped")
return nil
}
}
}
func (d *Source) tailContainerAttempt(ctx context.Context, container *ContainerConfig, outChan chan pipeline.Event, bo backoff.BackOff) error {
dockerReader, err := d.Client.ContainerLogs(ctx, container.ID, *container.logOptions)
if err != nil {
return fmt.Errorf("unable to read logs from container %s: %w", container.Name, err)
}
// Log connection (both initial and reconnections)
container.logger.Info("connected to container logs")
// reset backoff so for the next disconnect, the interval doesn't start from 30sec
bo.Reset()
var scanner *bufio.Scanner
// we use this library to normalize docker API logs (cf. https://ahmet.im/blog/docker-logs-api-binary-format-explained/)
if container.Tty {
scanner = bufio.NewScanner(dockerReader)
} else {
reader := dlog.NewReader(dockerReader)
scanner = bufio.NewScanner(reader)
}
readerChan := make(chan string)View on GitHub (pinned to 909b515798)
Solutions
- Confirm the container exists and its log driver supports reading: `docker inspect -f '{{.HostConfig.LogConfig}}' <name>` (avoid "none").
- Check the docker daemon/socket is reachable and permissions allow the logs API.
- With docker-socket-proxy, allow the containers/logs endpoints.
- This error is retried via the backoff passed to tailContainerAttempt — leave the source running and it will reconnect when the container/daemon returns.
Example fix
// before (daemon-compose service)
logging:
driver: none
// after
logging:
driver: json-file
options:
max-size: "10m" Defensive patterns
Strategy: retry
Validate before calling
// Go: verify the container still exists before tailing
_, err := cli.ContainerInspect(ctx, container.ID)
if err != nil {
// container gone; re-resolve by name instead of tailing a stale ID
return reResolve(ctx, container.Name)
} Try / catch
err := d.tailContainerAttempt(ctx, container, outChan, bo)
if err != nil && strings.Contains(err.Error(), "unable to read logs from container") {
d.WaitFor(time.After(bo.NextBackOff())) // backoff retry
} Prevention
- Avoid log driver "none" on containers whose logs you must read.
- For short-lived containers, prefer event-driven discovery over one-shot reads.
- Keep daemon socket local or use a proxy that allows the logs endpoint.
- Check container name resolution at startup and log clear warnings.
When it happens
Trigger: ContainerLogs called with a container ID that no longer exists (container removed between discovery and tail), docker daemon temporarily down, or a socket-proxy denying the /containers/{id}/logs endpoint; also bad log options (e.g. invalid tail/since values rejected by the daemon).
Common situations: Short-lived containers that exit and are removed while crowdsec is starting; docker daemon restart; log driver not supporting reading logs (e.g. "none"); socket-proxy blocking the logs route.
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 service %s: %w
- no container found named: %s, can't run one shot acquisition
- reader connection lost for container %s
- appsec datasource requires a hub. this is a bug, please repo
- appsec datasource requires a lapi client configuration. this
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/3e0ba54a91b928b4.
Report an issue: GitHub.