GoogleContainerTools/skaffold · warning
context cancelled for k8s job logging of pod of kubernetes j
Error message
context cancelled for k8s job logging of pod of kubernetes job: %s
What it means
This error is returned by the k8s job logger's waitForPodAndCheckLoggable-style wait loop when the parent context is cancelled before a pod event for the Kubernetes job is observed. It indicates the log-streaming setup was aborted because the caller (or a shutdown/timeout upstream) cancelled the context, not because the pod failed. It is a normal cancellation signal rather than a Kubernetes failure.
Source
Thrown at pkg/skaffold/k8sjob/logger/log.go:191
if err != nil {
return false, nil
}
done := make(chan bool)
go func() {
for event := range w.ResultChan() {
pod, ok := event.Object.(*corev1.Pod)
if ok {
podName = pod.Name
done <- true
break
}
}
}()
select {
case <-ctx.Done():
return false, fmt.Errorf("context cancelled for k8s job logging of pod of kubernetes job: %s", "id")
case <-done:
// Continue
case <-time.After(30 * time.Second): // Timeout after 30 seconds
return false, fmt.Errorf("timeout waiting for event from pod of kubernetes job: %s", id)
}
podLogOptions := &corev1.PodLogOptions{
Follow: true,
}
// Stream the logs
req := clientset.CoreV1().Pods(namespace).GetLogs(podName, podLogOptions)
podLogs, err := req.Stream(ctx)
if err != nil {
return false, nil
}
defer podLogs.Close()
io.Copy(tw, podLogs)View on GitHub (pinned to a1189de023)
Solutions
- No fix needed if cancellation was intentional (e.g. Ctrl-C); treat as expected shutdown
- If unexpected, check what cancels ctx upstream (parent deadline, signal handler, pipeline timeout) and extend it
- Increase retry tolerance: re-run the deploy so logging re-attaches to the job pod
- Handle this error distinctly from the timeout error so cancellations are not logged as failures
Example fix
// before
case <-ctx.Done():
return false, fmt.Errorf("context cancelled for k8s job logging of pod of kubernetes job: %s", "id")
// after
case <-ctx.Done():
return false, ctx.Err() // preserves real cause: context.Canceled vs context.DeadlineExceeded Defensive patterns
Strategy: try-catch
Validate before calling
// Go has no pre-check; verify ctx is live before starting
select {
case <-ctx.Done():
return fmt.Errorf("context already cancelled: %w", ctx.Err())
default:
} Type guard
// Narrow cancellation vs other errors
func isContextCancelled(err error) bool {
return errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded)
} Try / catch
err := startJobLogging(ctx, job)
if err != nil {
if errors.Is(err, context.Canceled) {
log.Println("log streaming cancelled by caller; shutting down cleanly")
return nil // expected, not a failure
}
return err
} Prevention
- Pass a context with an explicit timeout sized for pod startup
- Treat context.Canceled as a clean shutdown, not an error, in callers
- Log the cancellation cause upstream so silent cancels are traceable
When it happens
Trigger: The select in the goroutine-wrapped pod-event wait sees ctx.Done() fire before either the done channel closes or the 30-second timer expires — i.e. the user cancels the skaffold command, Ctrl-C, or an upstream deadline cancels ctx while waiting for the job's pod to appear.
Common situations: User aborts a skaffold deploy while k8s job logs are starting; test harnesses cancel contexts to stop log streaming; overall pipeline timeout cancels the context during job startup.
Related errors
- reading bytes from log stream: %w
- 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/e4b409c5e9243289.
Report an issue: GitHub.