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
- Verify the pod exists: kubectl get pod <name> -n <ns>; if gone, refresh the view and retry on the new pod
- Confirm the path format is exactly namespace/name with no extra segments
- If k9s just started, wait a few seconds for informer sync and retry the action
- 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
- Always pass the full namespace/name path, never a bare pod name
- Give k9s a few seconds on huge clusters before acting on freshly observed pods
- Refresh the pod view (key 0/reload) after reschedules before exec/log actions
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
- expecting Deployment resource
- expecting Pod resource
- no node assigned
- user is not authorized to run jobs
- user is not authorized to (un)suspend cronjobs
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/438b891d4b9eaeb4.
Report an issue: GitHub.