derailed/k9s · warning

unable to locate container status for %q

Error message

unable to locate container status for %q

What it means

checkRunningStatus scans the pod's Status.ContainerStatuses for a container by name and found none. The name being checked is not present in the pod's reported status list, so its state cannot be determined. Distinguish from a pod-spec problem: the container may exist in spec but be missing from status.

Source

Thrown at internal/view/container.go:225

	ports, ann, ok := c.listForwardable(path)
	if !ok {
		return nil
	}
	ShowPortForwards(c, c.GetTable().Path+"|"+path, ports, ann, startFwdCB)

	return nil
}

func checkRunningStatus(co string, ss []v1.ContainerStatus) error {
	var cs *v1.ContainerStatus
	for i := range ss {
		if ss[i].Name == co {
			cs = &ss[i]
			break
		}
	}
	if cs == nil {
		return fmt.Errorf("unable to locate container status for %q", co)
	}

	if render.ToContainerState(cs.State) != "Running" {
		return fmt.Errorf("Container %s is not running?", co)
	}

	return nil
}

func locateContainer(co string, cc []v1.Container) (*v1.Container, error) {
	for i := range cc {
		if cc[i].Name == co {
			return &cc[i], nil
		}
	}
	return nil, fmt.Errorf("unable to locate container named %q", co)
}

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Pass a name from Status.ContainerStatuses; for init/ephemeral containers, check Status.InitContainerStatuses or Status.EphemeralContainerStatuses instead.
  2. Wait/retry until the kubelet populates status (kubectl get pod -w or a watch) before invoking container operations.
  3. Verify the exact name: kubectl get pod <pod> -o jsonpath='{.status.containerStatuses[*].name}'.
  4. Refresh the view — a stale cached pod may no longer match the live object.

Example fix

// before
if err := checkRunningStatus(co, po.Status.ContainerStatuses); err != nil { ... }

// after: search the right status list per container kind
ss := po.Status.ContainerStatuses
if !inList(co, ss) { ss = po.Status.InitContainerStatuses }
if !inList(co, ss) { ss = po.Status.EphemeralContainerStatuses }
if err := checkRunningStatus(co, ss); err != nil { ... }
Defensive patterns

Strategy: validation

Validate before calling

func statusListFor(po *v1.Pod, co string) []v1.ContainerStatus {
    if inStatus(po.Status.ContainerStatuses, co) { return po.Status.ContainerStatuses }
    if inStatus(po.Status.InitContainerStatuses, co) { return po.Status.InitContainerStatuses }
    return po.Status.EphemeralContainerStatuses
}
if err := checkRunningStatus(co, statusListFor(po, co)); err != nil { return err }

Type guard

func containerStatusNamed(ss []v1.ContainerStatus, name string) (v1.ContainerStatus, bool) {
    for i := range ss {
        if ss[i].Name == name { return ss[i], true }
    }
    return v1.ContainerStatus{}, false
}

Try / catch

if err := checkRunningStatus(co, ss); err != nil {
    if strings.Contains(err.Error(), "unable to locate container status") {
    // refresh pod and select the status list matching the container kind before retrying once
    }
}

Prevention

When it happens

Trigger: Calling exec/attach/log-follow paths guarded by checkRunningStatus for a container that is an initContainer or ephemeralContainer — those live in Status.InitContainerStatuses/Status.EphemeralContainerStatuses, not ContainerStatuses; checking immediately after pod creation before the kubelet has reported status (status list empty or partial); a name mismatch (typo, different casing).

Common situations: Sidecars implemented as init containers (restartPolicy: Always) where the name only appears in init status; ephemeral debug containers; racing pod creation in controllers/tests; renamed containers during rollout while holding a stale name.

Related errors


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