Kubernetes Error Guide: 'no matches for kind in version' — Fix Unrecognized Resources
Fix the 'no matches for kind in version' error in Kubernetes: install missing CRDs, use the right apiVersion, and handle removed API groups on apply.
- #kubernetes
- #troubleshooting
- #errors
- #crds
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
kubectl apply fails with unable to recognize ...: no matches for kind "..." in version "...". This means the API server does not know about the resource type you are trying to create. Kubernetes can only accept a kind/apiVersion pair that is registered — either a built-in type, or a CustomResourceDefinition (CRD) that has been installed. If the CRD is not installed, or you used a wrong/removed apiVersion, the server has nothing to match your object against and rejects it before storing anything.
The literal error looks like this:
error: unable to recognize "app.yaml": no matches for kind "Certificate" in version "cert-manager.io/v1"
You will hit this most often when: applying a CR before its operator/CRD is installed, ordering matters in a manifest bundle, using an apiVersion that was removed in your cluster’s Kubernetes version, or targeting a cluster that simply does not have the add-on. The fix is to make the type known — install the CRD, correct the apiVersion, or apply resources in the right order.
Symptoms
kubectl applyreturnsno matches for kind "<Kind>" in version "<group>/<version>".- Only the custom/removed resources fail; built-in resources apply fine.
- The error is at apply time; nothing is created for that object.
kubectl api-resourcesdoes not list the kind, or lists a different version.
kubectl apply -f app.yaml
service/api created
deployment.apps/api created
error: unable to recognize "app.yaml": no matches for kind "Certificate" in version "cert-manager.io/v1"
Common Root Causes
1. The CRD (operator) is not installed
The most common cause: you are applying a custom resource (Certificate, Rollout, ServiceMonitor) but the controller that owns its CRD was never installed, so the type does not exist.
kubectl get crd | grep cert-manager
(no output)
Install the operator/CRDs first, then apply the custom resource.
2. Apply ordering — CRD and CR in the same bundle
If a single kubectl apply -f dir/ includes both a CRD and a CR that uses it, the CR can be evaluated before the CRD is fully established, producing this error transiently.
kubectl apply -f manifests/
Apply the CRD first (or re-run apply so the second pass finds the now-registered type).
3. Wrong or removed apiVersion
The kind exists but under a different apiVersion. A manifest written for an older cluster may reference a version that was removed (e.g. batch/v1beta1 CronJob, networking.k8s.io/v1beta1 Ingress, policy/v1beta1 PodDisruptionBudget).
kubectl api-resources | grep -i cronjob
cronjobs cj batch/v1 true CronJob
Update the manifest to the version the cluster serves (batch/v1).
4. Wrong cluster / context
You are pointed at a cluster that does not have the add-on installed (e.g. staging has cert-manager, the sandbox does not).
kubectl config current-context
5. A typo in group or kind
A misspelled group (cert-manger.io) or kind means nothing matches.
Diagnostic Workflow
Step 1: Read the exact kind and version
kubectl apply -f app.yaml
The message gives you kind and group/version — those are what must be registered.
Step 2: Check whether the type is served
kubectl api-resources | grep -i <kind>
kubectl api-versions | grep <group>
No match means the CRD is missing or the version is wrong.
Step 3: Check for the CRD
kubectl get crd | grep <group>
Step 4: Confirm the correct apiVersion for a built-in
kubectl explain <kind> | head -3
kubectl explain shows the currently served version for that kind.
Step 5: Install/fix and re-apply
kubectl apply -f <operator-or-crd>.yaml
kubectl wait --for condition=established crd/<name> --timeout=60s
kubectl apply -f app.yaml
Example Root Cause Analysis
A deploy pipeline applies an app bundle to a fresh cluster and fails on the TLS resource:
kubectl apply -f k8s/
deployment.apps/web created
service/web created
error: unable to recognize "k8s/certificate.yaml": no matches for kind "Certificate" in version "cert-manager.io/v1"
Checking whether the type exists:
kubectl api-resources | grep -i certificate
(no output)
And the CRD:
kubectl get crd | grep cert-manager
(no output)
cert-manager is not installed on this cluster, so Certificate is an unknown kind. Installing cert-manager (which registers the CRDs), waiting for them to establish, then re-applying resolves it:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.0/cert-manager.yaml
kubectl wait --for condition=established crd/certificates.cert-manager.io --timeout=60s
kubectl apply -f k8s/certificate.yaml
certificate.cert-manager.io/web-tls created
The type is now registered and the resource applies cleanly.
Prevention Best Practices
- Install CRDs/operators before the custom resources that use them; make CRD installation a distinct, earlier pipeline stage.
- Use
kubectl wait --for condition=established crd/<name>so applies do not race a not-yet-registered CRD. - Pin manifests to
apiVersions your target cluster version actually serves; scan for removed APIs withkubectl-convert,pluto, orkubentbefore upgrades. - Keep add-on manifests (cert-manager, Prometheus, Argo Rollouts) versioned alongside the app so a fresh cluster gets both.
- Verify
kubectl config current-contextin CI so you never apply against a cluster missing the add-on. See more in Kubernetes & Helm guides.
Quick Command Reference
# See the unrecognized kind/version
kubectl apply -f app.yaml
# Is the type served?
kubectl api-resources | grep -i <kind>
kubectl api-versions | grep <group>
# Is the CRD installed?
kubectl get crd | grep <group>
# Correct apiVersion for a built-in
kubectl explain <kind> | head -3
# Install CRDs, wait, then apply the CR
kubectl apply -f <operator>.yaml
kubectl wait --for condition=established crd/<name> --timeout=60s
kubectl apply -f app.yaml
Conclusion
no matches for kind "..." in version "..." means the API server does not recognize the resource type. The usual causes:
- The CRD/operator that defines the type is not installed.
- A CRD and its CR are applied together and race.
- A wrong or removed
apiVersion. - The wrong cluster/context (add-on absent).
- A typo in the group or kind.
Check kubectl api-resources and kubectl get crd to confirm the type is registered, install the CRD first, and pin the correct apiVersion. For ad-hoc triage, the free incident assistant can turn this apply error into the exact CRD or apiVersion fix.
Get 500 Battle-Tested DevOps AI Prompts — Free
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.