derailed/k9s · error

failed to locate pod %q: %w

Error message

failed to locate pod %q: %w

What it means

Container.fetchPod (internal/dao/container.go:135-141) looks up a pod by fully-qualified name (ns/pod) in the shared watch-factory cache via client.PodGVR. This error wraps the factory Get failure; it is a cache/informer lookup, not a live API call, so a pod that exists on the cluster can still be missed if the cache has not synced or the FQN is malformed.

Source

Thrown at internal/dao/container.go:138

			if status.InitContainerStatuses[i].Name == name {
				return &status.InitContainerStatuses[i]
			}
		}
	case ephIDX:
		for i := range status.EphemeralContainerStatuses {
			if status.EphemeralContainerStatuses[i].Name == name {
				return &status.EphemeralContainerStatuses[i]
			}
		}
	}

	return nil
}

func (c *Container) fetchPod(fqn string) (*v1.Pod, error) {
	o, err := c.getFactory().Get(client.PodGVR, fqn, true, labels.Everything())
	if err != nil {
		return nil, fmt.Errorf("failed to locate pod %q: %w", fqn, err)
	}
	var po v1.Pod
	err = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &po)
	return &po, err
}

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Verify the pod exists: kubectl get pod <name> -n <ns>; if gone, refresh the view and retry on the new pod
  2. Confirm the path format is exactly namespace/name with no extra segments
  3. If k9s just started, wait a few seconds for informer sync and retry the action
  4. Check that the namespace is watchable by the current user (RBAC on pods) so the cache can populate
Defensive patterns

Strategy: retry

Validate before calling

// Before using a pod path, confirm the informer cache has it.
func PodCached(f watch.Factory, fqn string) bool {
	_, err := f.Get(client.PodGVR, fqn, true, labels.Everything())
	return err == nil
}

Try / catch

// pod lookup: distinguish gone-vs-not-synced, retry briefly on cache miss.
err := dao.Inspect(ctx, podFQN)
if err != nil {
    if strings.Contains(err.Error(), "failed to locate pod") {
        if ok := wait.PollUntilContextTimeout(ctx, 500*time.Millisecond, 5*time.Second, true,
            func(ctx context.Context) (bool, error) { return PodCached(f, podFQN), nil }); ok == nil {
            err = dao.Inspect(ctx, podFQN) // cache caught up
        }
    }
    if err != nil { return err }
}

Prevention

When it happens

Trigger: Calling a container DAO method (exec, logs, shell) with a pod path that is not in the informer cache: typo in the pod name, wrong namespace in the ns/name pair, pod already deleted, or the pod informer has not finished its initial list right after k9s connects to a large cluster.

Common situations: Acting on a stale UI row after the pod was OOM-killed/rescheduled; scripts or plugin args passing a pod name without its namespace; slow cache sync on clusters with tens of thousands of pods; filtered contexts hiding the namespace from the informer's watch.

Related errors


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