GoogleContainerTools/skaffold · warning
port forwarding %v got terminated: output: %s
Error message
port forwarding %v got terminated: output: %s
What it means
The forward loop detects that its kubectl port-forward process terminated (scanning output or cmd.Wait error). It logs the buffered kubectl output and, unless the output contains "address already in use" (a transient condition the loop retries), it sends this error on errChan without blocking. It means the port-forward tunnel to the pod died and will be re-established by the forwarder's retry loop.
Source
Thrown at pkg/skaffold/kubernetes/portforward/kubectl_forwarder.go:167
time.Sleep(500 * time.Millisecond)
continue
}
// Kill kubectl on port forwarding error logs
go k.monitorLogs(ctx, &buf, cmd, pfe, errChan)
if err := cmd.Wait(); err != nil {
if ctx.Err() == context.Canceled {
log.Entry(ctx).Debugf("terminated %v due to context cancellation", pfe)
return
}
// To make sure that the log monitor gets cleared up
cancel()
s := buf.String()
log.Entry(ctx).Debugf("port forwarding %v got terminated: %s, output: %s", pfe, err, s)
if !strings.Contains(s, "address already in use") {
select {
case errChan <- fmt.Errorf("port forwarding %v got terminated: output: %s", pfe, s):
default:
}
}
time.Sleep(500 * time.Millisecond)
}
}
}
func portForwardArgs(ctx context.Context, kubeContext string, pfe *portForwardEntry) []string {
args := []string{"--pod-running-timeout", "1s", "--namespace", pfe.resource.Namespace}
_, disableServiceForwarding := os.LookupEnv("SKAFFOLD_DISABLE_SERVICE_FORWARDING")
switch {
case pfe.resource.Type == "service" && !disableServiceForwarding:
// Services need special handling: https://github.com/GoogleContainerTools/skaffold/issues/4522
podName, remotePort, err := findNewestPodForSvc(ctx, kubeContext, pfe.resource.Namespace, pfe.resource.Name, pfe.resource.Port)
if err == nil {
args = append(args, fmt.Sprintf("pod/%s", podName), fmt.Sprintf("%d:%d", pfe.localPort, remotePort))View on GitHub (pinned to a1189de023)
Solutions
- Check the `output:` portion of the message for kubectl's actual failure reason (e.g. connection refused, pod not found)
- Verify the target pod is running: kubectl get pod <pod> -n <ns>
- If the pod was restarted, the forwarder typically retries automatically — wait or restart skaffold dev
- Check network/VPN stability to the cluster; transient drops kill the tunnel
Defensive patterns
Strategy: retry
Validate before calling
// verify the target pod is ready before initiating the port-forward
pod, err := clientset.CoreV1().Pods(ns).Get(ctx, podName, metav1.GetOptions{})
if err != nil || pod.Status.Phase != corev1.PodRunning {
return fmt.Errorf("pod %s not ready for port-forward", podName)
} Try / catch
errChan := make(chan error, 1)
// forwarder sends termination errors here non-blocking
select {
case err := <-errChan:
if strings.Contains(err.Error(), "got terminated") {
// forwarder retries automatically; log and wait for re-establishment
}
case <-ctx.Done():
} Prevention
- Keep the cluster network/VPN stable during long dev sessions
- Avoid deleting/rescheduling the target pod while port-forwards are active
- Monitor pod restarts (kubectl get pods -w) during dev loops
- Ignore transient "address already in use" variants — the forwarder retries those itself
When it happens
Trigger: kubectl port-forward process exits: pod restarted/deleted during port-forward, network drop, connection to the pod refused, context timeout/cancellation propagated, or kubectl binary failure.
Common situations: Pod crashes or gets rescheduled while dev-loop is running; cluster node reboot; VPN/network interruption; target pod's container port stops listening.
Related errors
- getting server resources for group version: %w
- getting pods for namespace %q: %w
- Forward() called before kubectl forwarder was started
- STATUSCHECK_DEPLOYMENT_FETCH_ERR
- could not fetch deployments: %w
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/8d3d30ac7182e7bf.
Report an issue: GitHub.