ipfs/kubo · warning
error reading log message: %s
Error message
error reading log message: %s
What it means
The log-streaming HTTP endpoint tails the daemon log through a pipe: a goroutine reads lines with bufio.Reader.ReadString and writes them to the HTTP response. If the read fails (pipe closed, daemon-side writer gone, EOF), the reader pushes 'error reading log message: <err>' onto an internal channel and stops streaming.
Source
Thrown at core/corehttp/logs.go:44
case <-r.Context().Done(): // Client canceled request
case <-n.Context().Done(): // Node shutdown
case <-done: // log reader goroutine exitex
}
pipeReader.Close()
}()
errs := make(chan error, 1)
go func() {
defer close(errs)
defer close(done)
rdr := bufio.NewReader(pipeReader)
for {
// Read a line of log data and send it to the client.
line, err := rdr.ReadString('\n')
if err != nil {
errs <- fmt.Errorf("error reading log message: %s", err)
return
}
_, err = w.Write([]byte(line))
if err != nil {
// Failed to write to client, probably disconnected.
return
}
if f, ok := w.(http.Flusher); ok {
f.Flush()
}
if r.Context().Err() != nil {
return
}
}
}()
log.Info("log API client connected")
err := <-errs
if err != nil {View on GitHub (pinned to 329838acdf)
Solutions
- Reconnect the log stream client (e.g. rerun `ipfs log tail`); the error usually means the stream ended, most often due to daemon shutdown.
- Check whether the daemon is still running (`ipfs id`); restart it if it exited during the stream.
- Inspect daemon logs via the on-disk log file instead of the streaming endpoint to see what happened around the failure.
- If streaming repeatedly fails, report/inspect the pipe setup — a persistent read error indicates an I/O problem rather than a normal disconnect.
Example fix
// before: client keeps a fragile long-lived stream
ipfs log tail # dies with daemon
// after: tolerate stream end and reconnect with backoff
for {
ipfs log tail || true
sleep 2
} Defensive patterns
Strategy: retry
Validate before calling
// confirm the daemon is alive before (re)attaching a log stream
if err := shell.NewLocalShell().ID(); err != nil {
return fmt.Errorf("daemon not reachable, not a stream problem: %w", err)
} Try / catch
// client loop around the log stream
for {
err := tailLogs(ctx) // POST /api/v0/log/tail and stream
if ctx.Err() != nil { return ctx.Err() }
log.Printf("log stream ended: %v; reconnecting in 2s", err)
time.Sleep(2 * time.Second)
} Prevention
- Wrap log-tail clients in an auto-reconnect loop; streams legitimately end at daemon shutdown.
- Stop tailing before stopping the daemon to avoid interpreting shutdown as an error.
- Keep an on-disk log file fallback (GOLOG_FILE) for post-mortem when streams drop.
- Treat 'error reading log message' as stream termination, not data corruption.
When it happens
Trigger: While consuming the live log endpoint (used by `ipfs log tail`-style clients), the reading goroutine hits an error from rdr.ReadString('\n') — e.g. the log pipe writer was closed during daemon shutdown, or an I/O error on the pipe.
Common situations: Daemon shutting down while a client is tailing logs; log pipe closed unexpectedly; long-lived log streams dropped when the daemon restarts; embedded usages where the log writer is torn down independently of the HTTP handler.
Related errors
- err.Error()
- unexpected redirect
- e (stream error trailer header value)
- cannot read migration: %w
- unexpected error while checking writeablility of repo root:
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/46374bfdc7a787b9.
Report an issue: GitHub.