{"record":{"id":"216fb967107b9e46","repo":"GoogleContainerTools/skaffold","slug":"reading-bytes-from-log-stream-w","errorCode":null,"errorMessage":"reading bytes from log stream: %w","messagePattern":"reading bytes from log stream: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/skaffold/log/stream/stream.go","lineNumber":52,"sourceCode":"\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\tolog.Entry(ctx).Infof(\"%s interrupted\", formatter.Name())\n\t\t\treturn nil\n\t\tdefault:\n\t\t\t// Read up to newline\n\t\t\tline, err := r.ReadString('\\n')\n\t\t\t// As per https://github.com/kubernetes/kubernetes/blob/017b359770e333eacd3efcb4174f1d464c208400/test/e2e/storage/podlogs/podlogs.go#L214\n\t\t\t// Filter out the expected \"end of stream\" error message and\n\t\t\t// attempts to read logs from a container that was deleted due to re-deploy or\n\t\t\t// attempts to read logs from a container that is not ready yet.\n\t\t\tif err == io.EOF {\n\t\t\t\tif !isEmptyOrContainerNotReady(line) {\n\t\t\t\t\tformatter.PrintLine(out, line)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"reading bytes from log stream: %w\", err)\n\t\t\t}\n\t\t\tformatter.PrintLine(out, line)\n\t\t}\n\t}\n}\n\nfunc isEmptyOrContainerNotReady(line string) bool {\n\treturn line == \"\" ||\n\t\tstrings.HasPrefix(line, \"rpc error: code = Unknown desc = Error: No such container:\") ||\n\t\tstrings.HasPrefix(line, \"unable to retrieve container logs for \") ||\n\t\tstrings.HasPrefix(line, \"Unable to retrieve container logs for \")\n}\n","sourceCodeStart":34,"sourceCodeEnd":65,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/log/stream/stream.go#L34-L65","documentation":"While consuming a container's log stream, stream.go reads lines from the stream reader. If the underlying read fails (not a clean EOF), the error is wrapped so the caller knows bytes could not be read from the log stream. Clean EOFs are handled upstream as normal stream end; this error represents a real I/O failure.","triggerScenarios":"The bufio/scanner read over the pod log stream returns a non-EOF error: container/API connection dropped, context canceled mid-read, API server closed the watch/connection abnormally, or decompression/decode failure on the stream.","commonSituations":"Pod deleted or node rebooted mid 'skaffold dev' while logs stream; network drop to the cluster; Kubernetes context canceled by Ctrl-C racing the reader; long-lived stream hitting connection idle timeouts.","solutions":["Check cluster/pod health (kubectl get pod) and restart skaffold dev to re-establish the stream","For expected cancellations, treat errors.Is(err, context.Canceled) as normal shutdown and ignore","Improve network stability (VPN, keepalives) or lower log volume with container-stdin/false filters","Upgrade skaffold/client if the stream reader has a known idle-timeout bug"],"exampleFix":"// caller-side handling\nif err := streamContainerLogs(...); err != nil {\n    if errors.Is(err, context.Canceled) || strings.Contains(err.Error(), \"reading bytes from log stream\") && isShutdown(err) {\n        return nil // expected during teardown\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"func isTransientStreamError(err error) bool {\n    if errors.Is(err, context.Canceled) || errors.Is(err, io.ErrUnexpectedEOF) {\n        return true\n    }\n    var ne net.Error\n    return errors.As(err, &ne)\n}","tryCatchPattern":"err := streamContainerLogs(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"reading bytes from log stream\") {\n    if ctx.Err() != nil { return nil } // shutdown, ignore\n    if isTransientStreamError(err) {\n        return retryWithBackoff(3, time.Second, func() error { return streamContainerLogs(ctx, req) })\n    }\n    return err\n}","preventionTips":["Avoid long-idle streams through proxies/VPNs that kill connections; tune keepalives","Treat context cancellation during shutdown as a normal EOF, not an error","Check pod/node health when streams die mid-run (kubectl get events)","Upgrade skaffold if stream readers drop frequently on your cluster version"],"tags":["logging","kubernetes","stream","io"],"backgroundTag":"log-stream-read-failure","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}