GoogleContainerTools/skaffold · warning
reading bytes from log stream: %w
Error message
reading bytes from log stream: %w
What it means
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.
Source
Thrown at pkg/skaffold/log/stream/stream.go:52
select {
case <-ctx.Done():
olog.Entry(ctx).Infof("%s interrupted", formatter.Name())
return nil
default:
// Read up to newline
line, err := r.ReadString('\n')
// As per https://github.com/kubernetes/kubernetes/blob/017b359770e333eacd3efcb4174f1d464c208400/test/e2e/storage/podlogs/podlogs.go#L214
// Filter out the expected "end of stream" error message and
// attempts to read logs from a container that was deleted due to re-deploy or
// attempts to read logs from a container that is not ready yet.
if err == io.EOF {
if !isEmptyOrContainerNotReady(line) {
formatter.PrintLine(out, line)
}
return nil
}
if err != nil {
return fmt.Errorf("reading bytes from log stream: %w", err)
}
formatter.PrintLine(out, line)
}
}
}
func isEmptyOrContainerNotReady(line string) bool {
return line == "" ||
strings.HasPrefix(line, "rpc error: code = Unknown desc = Error: No such container:") ||
strings.HasPrefix(line, "unable to retrieve container logs for ") ||
strings.HasPrefix(line, "Unable to retrieve container logs for ")
}
View on GitHub (pinned to a1189de023)
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
Example fix
// caller-side handling
if err := streamContainerLogs(...); err != nil {
if errors.Is(err, context.Canceled) || strings.Contains(err.Error(), "reading bytes from log stream") && isShutdown(err) {
return nil // expected during teardown
}
return err
} Defensive patterns
Strategy: retry
Type guard
func isTransientStreamError(err error) bool {
if errors.Is(err, context.Canceled) || errors.Is(err, io.ErrUnexpectedEOF) {
return true
}
var ne net.Error
return errors.As(err, &ne)
} Try / catch
err := streamContainerLogs(ctx, req)
if err != nil && strings.Contains(err.Error(), "reading bytes from log stream") {
if ctx.Err() != nil { return nil } // shutdown, ignore
if isTransientStreamError(err) {
return retryWithBackoff(3, time.Second, func() error { return streamContainerLogs(ctx, req) })
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- context cancelled for k8s job logging of pod of kubernetes j
- starting logger: %w
- starting logger: %w
- starting logger: %w
- c.Message (pod status condition message)
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/216fb967107b9e46.
Report an issue: GitHub.