{"record":{"id":"1108e998fe9a1745","repo":"derailed/k9s","slug":"stream-closed-w-for-s","errorCode":null,"errorMessage":"stream closed: %w for %s","messagePattern":"stream closed: %w for (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"internal/dao/pod.go","lineNumber":522,"sourceCode":"\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif droppedLines > 0 {\n\t\t\tslog.Warn(\"Total log lines dropped during stream\",\n\t\t\t\tslogs.Container, opts.Info(),\n\t\t\t\tslogs.Count, droppedLines,\n\t\t\t)\n\t\t}\n\n\t\tif errors.Is(err, io.EOF) {\n\t\t\tif len(bytes) > 0 {\n\t\t\t\t// Emit trailing partial line before EOF\n\t\t\t\tout <- opts.ToLogItem(tview.EscapeBytes(bytes))\n\t\t\t}\n\t\t\tslog.Debug(\"Log reader reached EOF\", slogs.Container, opts.Info())\n\t\t\tout <- opts.ToErrLogItem(fmt.Errorf(\"stream closed: %w for %s\", err, opts.Info()))\n\t\t\treturn streamEOF\n\t\t}\n\n\t\t// Non-EOF error\n\t\tslog.Debug(\"Log stream error, will retry connection\",\n\t\t\tslogs.Container, opts.Info(),\n\t\t\tslogs.Error, fmt.Errorf(\"stream error: %w for %s\", err, opts.Info()),\n\t\t)\n\t\treturn streamError\n\t}\n}\n\n// MetaFQN returns a fully qualified resource name.\nfunc MetaFQN(m *metav1.ObjectMeta) string {\n\tif m.Namespace == \"\" {\n\t\treturn m.Name\n\t}\n","sourceCodeStart":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/pod.go#L504-L540","documentation":"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.","triggerScenarios":"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.","commonSituations":"Reading logs of Completed Job pods without follow; containers restarting mid-tail; short-lived pods whose logs end as soon as the process finishes.","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)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"for item := range podDAO.Logs(ctx, opts) {\n    if item.IsErr && strings.Contains(item.Message, \"stream closed\") && strings.Contains(item.Message, \"EOF\") {\n        break // normal end of stream: finalize UI, do not show as error\n    }\n}","preventionTips":["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"],"tags":["kubernetes","logs","eof","stream"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}