Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Kubernetes & Helm By James Joyner IV · · 9 min read

Kubernetes Error Guide: 'Error from server (NotFound)' Resource Not Found

Fix Error from server (NotFound) in kubectl: wrong namespace or context, deleted resources, and typos. Learn to find where your object actually lives.

  • #kubernetes-helm
  • #troubleshooting
  • #errors
  • #kubectl

Exact Error Message

When kubectl asks the API server for an object that does not exist in the namespace and context it is looking at, the request returns HTTP 404 and kubectl prints a NotFound status error:

Error from server (NotFound): pods "payments-api-7d9f8b6d-2xqzt" not found

The same shape appears for any resource kind:

Error from server (NotFound): deployments.apps "checkout" not found
Error from server (NotFound): services "redis" not found
Error from server (NotFound): error when deleting "job.yaml": jobs.batch "import" not found

The text inside the parentheses is the API Reason (NotFound), and the message names the exact <resource> "<name>" the server could not locate.

What the Error Means

NotFound is a server-side answer, not a connectivity failure. kubectl successfully reached the API server, authenticated, and was authorized — the server simply has no object matching that group/version/kind, name, and namespace. The “Error from server” prefix confirms the round trip completed; contrast this with The connection to the server was refused, which never reaches the API at all.

The crucial detail is scope. Almost every namespaced lookup is implicitly qualified by the current namespace of your kubeconfig context. If the object exists but lives in a different namespace — or you are pointed at a different cluster entirely — the server correctly reports NotFound because the object is not where you asked. The error is almost always about where you are looking, not whether the object exists somewhere.

Common Causes

  • Wrong namespace — the resource exists, but in another namespace, and your context defaults to default (or some other namespace).
  • Wrong context/cluster — your kubeconfig is pointed at a different cluster than the one holding the object.
  • The object was deleted — a controller, GC, TTL, or another operator removed it; a stale kubectl delete race is common.
  • Typo or wrong name — the pod’s generated suffix changed after a redeploy, so a copy-pasted name is now stale.
  • Wrong resource kind/alias — asking for pod/x when x is actually a Deployment, or a CRD whose short name differs.
  • CRD not installed — referencing a custom kind whose CustomResourceDefinition is absent reports the kind as not found.
  • Pruned by GitOps — Argo CD or Flux pruned the object because it left the desired state.

How to Reproduce the Error

Create a pod in one namespace, then look for it in another:

apiVersion: v1
kind: Pod
metadata:
  name: demo
  namespace: team-a
spec:
  containers:
    - name: app
      image: registry.k8s.io/pause:3.9
kubectl apply -f demo.yaml
kubectl get pod demo            # defaults to "default" namespace
Error from server (NotFound): pods "demo" not found

The pod exists in team-a, but the bare kubectl get pod demo looked in default.

Diagnostic Commands

# Which context and namespace am I actually using right now?
kubectl config current-context
kubectl config view --minify -o jsonpath='{..namespace}'

# Search every namespace for the object by name
kubectl get pods -A | grep payments-api

# List the real names in the namespace you expect it in
kubectl get pods -n team-a

# Confirm the resource kind/aliases the API actually serves
kubectl api-resources | grep -i deploy

# Did something delete it? Look for deletion events cluster-wide
kubectl get events -A --field-selector reason=Killing

# Confirm a CRD is installed before querying its custom kind
kubectl get crd | grep mycompany

The first two commands are the most important: they reveal the implicit namespace and cluster every lookup is scoped to.

Step-by-Step Resolution

1. Confirm your current scope. Most NotFound errors disappear once you see where kubectl is pointed:

kubectl config current-context
kubectl config view --minify -o jsonpath='{..namespace}'

If the namespace is empty, kubectl is using default.

2. Find where the object actually lives. Search all namespaces:

kubectl get <kind> -A | grep <name>

If it shows up under a different namespace, add -n <namespace> to your command (or set it as the context default with kubectl config set-context --current --namespace=<ns>).

3. Verify the exact name. Pod names carry a generated suffix that changes on every rollout. List the live names instead of trusting a copied one:

kubectl get pods -n <ns>

Re-run your command with the current name.

4. Check the right cluster. If the object is in no namespace anywhere, you may be on the wrong cluster. Switch context:

kubectl config get-contexts
kubectl config use-context <correct-context>

5. Rule out deletion. If the object existed minutes ago, look for the actor that removed it — a Job TTL, a CronJob’s history limit, GitOps prune, or a manual delete. Events and the controller’s logs name the cause. For GitOps, check whether the manifest still exists in the source repository; a prune means the desired state no longer includes it.

6. Confirm the kind is served. For custom resources, the CRD must be installed first. If kubectl api-resources | grep <kind> is empty, install the operator/CRD before the custom object can be found.

Prevention and Best Practices

  • Always pass -n <namespace> (or -A) in scripts and runbooks; never rely on the context’s default namespace for automation.
  • Use label selectors (kubectl get pods -l app=payments) instead of generated pod names, which change every deploy.
  • Name your contexts clearly (cluster + environment) so kubectl config current-context is unambiguous in an incident.
  • In CI, set --context explicitly so a developer’s local default cannot leak into a pipeline.
  • For GitOps, treat NotFound after a sync as expected when a manifest was removed — verify the source before recreating.
  • Add a shell prompt segment (kube-ps1 or starship) that shows the live cluster and namespace, eliminating the most common cause at a glance. More patterns in the Kubernetes & Helm guides.

Frequently Asked Questions

The pod was running a second ago — why is it NotFound now? Pods are ephemeral. A rollout, eviction, node drain, or CrashLoop replacement gives the new pod a different generated name. List current pods with kubectl get pods -n <ns> and use the live name.

kubectl get pods -A shows it, but my command still fails. Why? Your command is missing the namespace. -A searches everywhere, but a normal get/delete uses the context’s default namespace. Add -n <namespace> matching the one shown in the -A output.

Is NotFound ever a permissions problem? No. A permissions problem returns Forbidden (403). NotFound (404) means the server looked and the object is not there in that scope. If you suspect RBAC, you would see cannot get resource instead.

Why does deleting an already-deleted object error instead of succeeding? kubectl delete <name> errors with NotFound if the object is already gone. Use kubectl delete --ignore-not-found in scripts to make deletes idempotent.

My custom resource returns NotFound for both the object and a fresh get. The CRD is probably not installed. Run kubectl get crd | grep <group>; if empty, the API does not serve that kind yet — install the operator first.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.