derailed/k9s · error

pod must be running. Current status=

Error message

pod must be running. Current status=%v

What it means

ensurePodPortFwdAllowed (internal/view/pf_extender.go:125) fetches the pod and rejects the operation unless pod.Status.Phase == v1.PodRunning. The Kubernetes portforward API requires an active sandbox, which only exists once the pod is Running. The message reports the actual phase (Pending, Succeeded, Failed, Unknown).

Solutions

  1. Wait for the pod to reach Running (watch 'kubectl get pod <name> -w' until STATUS=Running) and retry
  2. If the pod is Succeeded/Failed (Job), rerun the Job or forward to a pod from an active workload
  3. Check events for scheduling/image problems: 'kubectl describe pod <name>' (ImagePullBackOff, Pending reasons)
  4. For multi-replica workloads, forward from a replica that is Running instead of the one selected

Example fix

// before: port-forward while pod is Pending
// -> pod must be running. Current status=Pending

# after: wait for Running, then retry
kubectl get pod mypod -w   # wait for STATUS=Running
# in k9s: shift+f again
Defensive patterns

Strategy: validation

Validate before calling

// check pod phase before attempting a forward
pod, err := fetchPod(factory, podName)
if err != nil { return err }
if pod.Status.Phase != v1.PodRunning {
    return fmt.Errorf("pod is %s; wait for Running before port-forwarding", pod.Status.Phase)
}

Try / catch

// if calling the k8s portforward API directly, expect SPDY errors on non-running pods and re-check phase
if err := pf.Start(); err != nil {
    if pod, perr := fetchPod(factory, podName); perr == nil && pod.Status.Phase != v1.PodRunning {
        return fmt.Errorf("pod not Running (%s): %w", pod.Status.Phase, err)
    }
    return err
}

Prevention

When it happens

Trigger: Starting a port-forward on a pod that is Pending (still pulling images / scheduling), Succeeded or Failed (Job pods), or Unknown (lost node). Also triggered by forwarding from a Deployment/StatefulSet immediately after creation before the pod transitions to Running.

Common situations: Rollouts in progress: user hits shift+f right after kubectl apply; completed/failed Job pods that still appear in the pod list; CrashLoopBackOff pods whose phase is Running intermittently (this one passes the phase check but fails later); node not ready.

Related errors


AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15). Data as JSON: /api/errors/e29f05242f790a1e. Report an issue: GitHub.

Appendix: source

Thrown at internal/view/pf_extender.go:125

func (p *PortForwardExtender) portForwardContext(ctx context.Context) context.Context {
	if bc := p.App().BenchFile; bc != "" {
		ctx = context.WithValue(ctx, internal.KeyBenchCfg, p.App().BenchFile)
	}

	return context.WithValue(ctx, internal.KeyPath, p.GetTable().GetSelectedItem())
}

// ----------------------------------------------------------------------------
// Helpers...

func ensurePodPortFwdAllowed(factory dao.Factory, podName string) error {
	pod, err := fetchPod(factory, podName)
	if err != nil {
		return err
	}
	if pod.Status.Phase != v1.PodRunning {
		return fmt.Errorf("pod must be running. Current status=%v", pod.Status.Phase)
	}

	return nil
}

func runForward(v ResourceViewer, pf watch.Forwarder, f *portforward.PortForwarder) {
	v.App().factory.AddForwarder(pf)

	v.App().QueueUpdateDraw(func() {
		DismissPortForwards(v, v.App().Content.Pages)
	})

	pf.SetActive(true)
	if err := f.ForwardPorts(); err != nil {
		v.App().Flash().Warnf("PortForward failed for %s: %s. Deleting!", pf.ID(), err)
	}
	v.App().QueueUpdateDraw(func() {
		v.App().factory.DeleteForwarder(pf.ID())

View on GitHub (pinned to 2d3ccc6ba2)