Platforms and DevOps
cert-manager Certificate READY False: find the failing step
READY: False Message: Issuing certificate as Secret does not existA Certificate stuck at READY False means cert-manager has not obtained a signed certificate yet, and the reason is in one of the resources it created underneath. For ACME issuers such as Let's Encrypt the chain is Certificate → CertificateRequest → Order → Challenge; the first resource in that chain that reports an error is the one to fix.
Quick fix
The Challenge resource usually holds the CA's exact error message.
Walk down the chain in the Certificate's namespace:
kubectl describe certificate example-com -n web
kubectl get certificaterequest,order,challenge -n web
kubectl describe challenge -n web
kubectl describe clusterissuer letsencrypt-prod
The Status and Events of the Challenge usually contain the CA's exact message (for example a 404, a timeout, or a DNS problem). Fix that, then let cert-manager retry or delete the failed CertificateRequest to start over.
Causes
Most stuck Certificates fail at the Challenge: an HTTP-01 path the CA cannot reach, or DNS-01 with wrong credentials or zones.
1. HTTP-01 challenge cannot be reached
The CA must fetch http://<domain>/.well-known/acme-challenge/<token> through your ingress. cert-manager creates a temporary solver pod, Service and Ingress for it.
- Confirm: the Challenge shows
Waiting for HTTP-01 challenge propagationor an error likewrong status code '404';curl http://example.com/.well-known/acme-challenge/testfrom outside never reaches the cluster. - Fix: make the solver's
ingressClassName(or class annotation) match your controller, expose port 80 on the controller's LoadBalancer, and exempt the challenge path from forced HTTPS redirects and authentication middleware. DNS for the name must point at the ingress load balancer.
2. DNS-01 credentials, zone or propagation
- Confirm: the Challenge reports API errors (
403,invalid credentials),NXDOMAIN, or keeps waiting for propagation. - Fix: check the Secret referenced by the solver and the provider permissions; make sure the solver targets the zone the domain is delegated to. When the cluster uses split-horizon DNS, configure the controller's
--dns01-recursive-nameserverswith public resolvers. See NXDOMAIN.
3. Issuer not Ready or referenced wrongly
- Confirm:
kubectl get issuer,clusterissuer -Ashows READY False, or the CertificateRequest says the issuer was not found. - Fix: an
Issueris namespaced and only serves Certificates in the same namespace; usekind: ClusterIssuerinissuerReffor a cluster-wide issuer. Check the ACMEserverURL, email and private key Secret.
4. The CA refuses the order
- Confirm: the Order or CertificateRequest message contains
rateLimited,caa, orrejectedIdentifier. - Fix: see Let's Encrypt rate limits and CAA record prevents issuance. Names that are not valid public DNS names cannot be issued by a public CA.
5. Secret or webhook problems
- Confirm: events mention a conflict with an existing Secret, or the cert-manager webhook is unreachable (
failed calling webhook). - Fix: make sure only one Certificate manages a given
secretName; check that the cert-manager, cainjector and webhook pods are running and that network policies allow the API server to reach the webhook.
Fixes by environment
The failing step is found the same way everywhere; what differs is how the challenge reaches the CA through an ingress, a Gateway or a load balancer.
Ingress-based annotation (cert-manager.io/cluster-issuer): cert-manager's ingress-shim creates the Certificate for you; describe it by the name of the tls.secretName.
Gateway API: HTTP-01 through Gateway API needs the solver configured with gatewayHTTPRoute and a Gateway listener on port 80.
Private clusters and clusters behind NAT: HTTP-01 needs a public route to port 80; otherwise use DNS-01.
Cloud load balancers: health checks or WAF rules on the load balancer can block or redirect challenge requests; exempt the path.
Staging first: a staging ClusterIssuer avoids burning production limits while you debug.
Don't do this
- Delete and recreate the Certificate in a loop. Each new Order counts toward CA limits; fix the failing step first.
- Disable HTTPS redirects globally to let the challenge through. Exempt
/.well-known/acme-challenge/only. - Copy a certificate into the Secret by hand and leave the Certificate broken. It will not renew, and it will expire silently.
FAQ
How long should a Certificate take to become Ready?
With a working HTTP-01 or DNS-01 setup, usually well under a few minutes; DNS-01 adds the propagation wait. If it is still not Ready after ten minutes, look at the Challenge resources rather than waiting longer.
How do I force cert-manager to retry?
cert-manager retries failed requests with a back-off. After fixing the cause you can delete the failed CertificateRequest so a new one is created, or use the cmctl tool (cmctl renew <certificate>) to trigger issuance.
Should I test with the Let's Encrypt staging server?
Yes. Create a separate ClusterIssuer pointing at https://acme-staging-v02.api.letsencrypt.org/directory and switch the Certificate's issuerRef to the production issuer only after it becomes Ready. Failed production attempts count toward rate limits.