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

  1. No fix needed if cancellation was intentional (e.g. Ctrl-C); treat as expected shutdown
  2. If unexpected, check what cancels ctx upstream (parent deadline, signal handler, pipeline timeout) and extend it
  3. Increase retry tolerance: re-run the deploy so logging re-attaches to the job pod
  4. 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

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


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/e4b409c5e9243289. Report an issue: GitHub.