derailed/k9s · info
stream closed: %w for %s
Error message
stream closed: %w for %s
What it means
readLogs treats io.EOF as the clean end of the log stream: it flushes any trailing partial line, emits this ErrLogItem, and returns streamEOF (which stops the retry loop — only streamError retries). It is informational: the reader consumed everything the server sent and the connection closed normally.
Source
Thrown at internal/dao/pod.go:522
}
}
continue
}
if droppedLines > 0 {
slog.Warn("Total log lines dropped during stream",
slogs.Container, opts.Info(),
slogs.Count, droppedLines,
)
}
if errors.Is(err, io.EOF) {
if len(bytes) > 0 {
// Emit trailing partial line before EOF
out <- opts.ToLogItem(tview.EscapeBytes(bytes))
}
slog.Debug("Log reader reached EOF", slogs.Container, opts.Info())
out <- opts.ToErrLogItem(fmt.Errorf("stream closed: %w for %s", err, opts.Info()))
return streamEOF
}
// Non-EOF error
slog.Debug("Log stream error, will retry connection",
slogs.Container, opts.Info(),
slogs.Error, fmt.Errorf("stream error: %w for %s", err, opts.Info()),
)
return streamError
}
}
// MetaFQN returns a fully qualified resource name.
func MetaFQN(m *metav1.ObjectMeta) string {
if m.Namespace == "" {
return m.Name
}
View on GitHub (pinned to 2d3ccc6ba2)
Solutions
- Treat it as normal end-of-stream, not a failure
- Use follow mode if the stream must stay open across container restarts
- If logs end unexpectedly, check restart count and previous logs (kubectl logs -p)
Defensive patterns
Strategy: try-catch
Try / catch
for item := range podDAO.Logs(ctx, opts) {
if item.IsErr && strings.Contains(item.Message, "stream closed") && strings.Contains(item.Message, "EOF") {
break // normal end of stream: finalize UI, do not show as error
}
} Prevention
- Render ErrLogItems containing EOF as 'stream ended' status, not as failures
- Use follow mode only when you truly need continuous output; plain reads always EOF
- After EOF on short-lived pods, check kubectl logs -p for the previous instance
When it happens
Trigger: A non-follow log request reaching the end of output; a container exiting while logs are tailed; the server closing the stream after container termination.
Common situations: Reading logs of Completed Job pods without follow; containers restarting mid-tail; short-lived pods whose logs end as soon as the process finishes.
Related errors
- failed to maintain log stream after %d retries
- dialLogs - no connection to dial
- expecting a context factory
- expecting a job resource
- no factory in context
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/1108e998fe9a1745.
Report an issue: GitHub.