Skip to content

Fixing kubectl 'the server doesn't have a resource type'

Rules out the wrong-cluster case first, then checks whether the resource is a CRD that was never applied, isn't yet Established, or is being hidden from discovery by RBAC or a broken aggregated API. It does not cover ordinary typos in a resource name that IS registered — kubectl's own suggestion output usually catches those — and it is not a guide to writing CRDs.

Unverifiedno reproductions yetWhy this confidence?
Revision 1published by DevYou curationrevision history
Run the diagnosisEvidence and compatibility

Symptoms

The diagnostic path

8 steps. Every step is written out below in full — the interactive version simply follows the branches for you.

  1. Step 1 · Startkubectl: the server doesn't have a resource type "<name>"

    Kubernetes' supported kubectl-to-API-server version skew is +/-1 minor version and does not, on its own, make a resource type disappear — for a built-in resource this error essentially never means version skew. It means the API server kubectl is actually talking to right now doesn't have that resource type registered at all.

    What happens next

    • passed step 2, Confirm which cluster/context kubectl is actually talking to
  2. Step 2 · TestConfirm which cluster/context kubectl is actually talking to

    The single most common cause of this error is simply querying the wrong cluster.

    Read-onlysh
    kubectl config current-context && kubectl cluster-info

    Expected result

    staging-cluster
    Kubernetes control plane is running at https://staging-api.example.com:6443

    What happens next

    • passed step 3, Check whether the resource is registered at all on this cluster
    • failed step 4, Fix: switch to the intended context
    • unknown step 4, Fix: switch to the intended context
  3. Step 3 · TestCheck whether the resource is registered at all on this cluster

    This lists every resource type the API server currently knows about, built-in or custom.

    Read-onlysh
    kubectl api-resources -o wide | grep -i <resource-name>

    Expected result

    (no output)

    What happens next

    • passed step 5, Check whether the CustomResourceDefinition is actually installed
    • failed step 6, Root cause: RBAC or a broken aggregated API is hiding it from discovery
    • unknown step 6, Root cause: RBAC or a broken aggregated API is hiding it from discovery
  4. Step 4 · FixFix: switch to the intended context

    If the current context points at a different cluster than intended, switch and retry before investigating anything else.

    Changes statesh

    Changes system or service state. Review before running.

    Changes kubectl's active context for all subsequent commands using this kubeconfig; it does not read or modify any credentials, only which cluster/context is currently selected.

    kubectl config use-context <correct-context>
  5. Step 5 · TestCheck whether the CustomResourceDefinition is actually installed

    The resource isn't listed at all — for anything that isn't a Kubernetes built-in, it needs its CRD applied to this cluster before it can be used, as a one-time, cluster-scoped step separate from creating instances of the resource.

    Read-onlysh
    kubectl get crd | grep -i <resource-plural>.<group>

    Expected result

    (no output)

    What happens next

    • passed step 7, Fix: apply the missing CustomResourceDefinition
    • failed step 8, Root cause: the CRD exists but isn't Established, or its scope doesn't match
    • unknown step 8, Root cause: the CRD exists but isn't Established, or its scope doesn't match
  6. Step 6 · Root causeRoot cause: RBAC or a broken aggregated API is hiding it from discovery

    The resource IS listed by api-resources, yet kubectl still errors on it — this points at API discovery, not registration. Either RBAC is restricting the current identity's access to the discovery endpoints for that API group, or (for an aggregated API server, not a plain CRD) the backing APIService is unavailable. Check for APIServices reporting Available=False.

    Read-onlysh
    kubectl get apiservices | grep False

    Expected result

    v1beta1.metrics.k8s.io   metrics-server/metrics-server   False (FailedDiscoveryCheck)   3h
  7. Step 7 · FixFix: apply the missing CustomResourceDefinition

    No matching CRD exists on this cluster. Apply the manifest that defines it — this is separate from, and must happen before, creating any actual custom resource of that type.

    Changes statesh

    Changes system or service state. Review before running.

    Registers the CustomResourceDefinition cluster-wide, making the resource type available in every namespace; existing custom resource objects elsewhere are unaffected, but any controller expected to own this CRD needs to already be compatible with its schema.

    kubectl apply -f <crd-manifest>.yaml
  8. Step 8 · Root causeRoot cause: the CRD exists but isn't Established, or its scope doesn't match

    The CRD is present but the resource still doesn't show in api-resources. Check the CRD's own status — the API server only serves the resource once its Established condition is True, and there can be a brief window right after apply where it isn't yet. Also check whether the CRD is Namespaced or Cluster scoped and whether it's being queried the wrong way (a cluster-scoped resource queried with -n <namespace> can look absent).

    Read-onlysh
    kubectl get crd <resource-plural>.<group> -o jsonpath='{.status.conditions}'

    Expected result

    [{"type":"Established","status":"True",...},{"type":"NamesAccepted","status":"True",...}]

Sources

Why this confidence?

What would strengthen it: 6 more independent reproductions. Reproductions from 3 more distinct environments.