juanfont/headscale · warning
reading container logs: %w
Error message
reading container logs: %w
What it means
Returned by HeadscaleInContainer.ReadLog when the underlying Docker API call to stream the headscale container's stdout/stderr logs fails. It wraps the error from dockertestutil.WriteLog, which executes a log-retrieval request against the Docker daemon. This is a test-harness error, not a headscale server error.
Source
Thrown at integration/hsic/hsic.go:727
_ = t.pool.Purge(t.pgContainer)
}
return stdoutPath, stderrPath, t.pool.Purge(t.container)
}
// WriteLogs writes the current stdout/stderr log of the container to
// the given [io.Writer]s.
func (t *HeadscaleInContainer) WriteLogs(stdout, stderr io.Writer) error {
return dockertestutil.WriteLog(t.pool, t.container, stdout, stderr)
}
// ReadLog returns the current stdout and stderr logs from the headscale container.
func (t *HeadscaleInContainer) ReadLog() (string, string, error) {
var stdout, stderr bytes.Buffer
err := dockertestutil.WriteLog(t.pool, t.container, &stdout, &stderr)
if err != nil {
return "", "", fmt.Errorf("reading container logs: %w", err)
}
return stdout.String(), stderr.String(), nil
}
// SaveLog saves the current stdout log of the container to a path
// on the host system.
func (t *HeadscaleInContainer) SaveLog(path string) (string, string, error) {
return dockertestutil.SaveLog(t.pool, t.container, path)
}
func (t *HeadscaleInContainer) SaveMetrics(savePath string) error {
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://"+net.JoinHostPort(t.hostname, "9090")+"/metrics", nil)
if err != nil {
return fmt.Errorf("creating metrics request: %w", err)
}
resp, err := http.DefaultClient.Do(req)View on GitHub (pinned to 565fd254d0)
Solutions
- Check that the container is still running before reading logs (call ReadLog before Shutdown/TearDown)
- Run `go run ./cmd/hi doctor` and `go run ./cmd/hi cleanup` to remove stale containers/networks from previous runs
- Verify the Docker daemon is responsive (`docker ps`) and that no concurrent integration run is purging shared resources
- Treat the error as non-fatal in cleanup paths: log it and continue, since the test verdict rarely depends on log retrieval
Example fix
// before
stdout, stderr, err := headscale.ReadLog()
if err != nil {
t.Fatalf("failed to read logs: %s", err)
}
// after (log-collection is best-effort during cleanup)
stdout, stderr, err := headscale.ReadLog()
if err != nil {
t.Logf("could not read container logs: %s", err)
} Defensive patterns
Strategy: try-catch
Try / catch
stdout, stderr, err := headscale.ReadLog()
if err != nil {
// log collection is diagnostic only; never fail the test verdict on it
t.Logf("headscale logs unavailable: %v", err)
stdout, stderr = "", ""
} Prevention
- Always collect logs before calling Shutdown/TearDown/purge
- Treat log retrieval as best-effort in cleanup helpers
- Run `hi cleanup` between runs so stale containers don't confuse log lookups
When it happens
Trigger: Calling scenario headscale.ReadLog() (typically in test cleanup or failure handlers) when the container has already been purged/stopped, the Docker daemon connection is broken, or the container runtime returned an error streaming logs.
Common situations: Calling ReadLog after TearDown/Shutdown has purged the container; Docker daemon restarted mid-test; test-suite container removed by a concurrent run or `hi cleanup`; dockertest pool timeouts.
Related errors
- creating headscale container: %w
- creating tailscale node: %w
- extracting logs: %w
- demultiplexing container logs: %w
- creating certificates for derp test: %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/0b27a2e7da532029.
Report an issue: GitHub.