Kubernetes Error Guide: 'default backend - 404' from ingress-nginx
Fix default backend - 404 from ingress-nginx: resolve missing Ingress rules, ingressClassName mismatch, empty endpoints, wrong pathType, and host header issues.
- #kubernetes
- #troubleshooting
- #errors
- #ingress
Exact Error Message
A request through an ingress-nginx controller returns the controller’s fallback page:
$ curl -i http://app.example.com/
HTTP/1.1 404 Not Found
Date: Thu, 25 Jun 2026 10:14:02 GMT
Content-Type: text/html
Content-Length: 21
Connection: keep-alive
default backend - 404
Browsers may instead show the styled variant:
404 Not Found
nginx
What the Error Means
default backend - 404 is returned by ingress-nginx’s built-in default backend when no Ingress rule matches the incoming request. The controller picks a backend by matching the request’s Host header and path against the Ingress objects it manages. If nothing matches — or if a matching Ingress points at a Service with no healthy endpoints — the controller routes to its catch-all default backend, which answers every request with this 404.
The key point: the 404 comes from ingress-nginx, not from your application. Your app may be perfectly healthy; the controller simply never forwarded the request to it. This distinguishes it from an application-level 404 (which would carry your app’s own error page and server header).
Common Causes
- No Ingress rule matches the host or path. There is no rule for the requested
Host, or the path prefix does not match. ingressClassNamemismatch. The Ingress names a class the controller does not watch, so the controller ignores the Ingress entirely.- Empty endpoints. The target Service has no
Readyendpoints — selector mismatch, wrong port, or pods notReady. - Wrong
path/pathType.ExactvsPrefixmismatch, or a path that does not align with how the app serves routes. - Host header mismatch. The client sends a different
Host(or none) than the rule’shost:. - TLS / SNI mismatch. HTTPS request’s SNI does not match any configured host, so it falls to the default server.
- Ingress in the wrong namespace. The Ingress and the target Service are in different namespaces; ingress-nginx only resolves Services in the Ingress’s own namespace.
rewrite-targetmisconfiguration. A rewrite/capture-group annotation strips the path so the upstream sees a route it does not serve.
How to Reproduce the Error
Create an Ingress whose host does not match the request:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
# Request a host the Ingress does NOT define
curl -i -H 'Host: wrong.example.com' http://<INGRESS_LB_IP>/
HTTP/1.1 404 Not Found
...
default backend - 404
No rule matches wrong.example.com, so the controller returns its default backend.
Diagnostic Commands
# Does the Ingress exist, and what class / host / backend does it use?
kubectl get ingress -A
kubectl describe ingress web -n prod
kubectl get ingress web -n prod -o jsonpath='{.spec.ingressClassName}{"\n"}'
# Does the target Service have endpoints?
kubectl get endpoints web -n prod
kubectl get endpointslices -n prod -l kubernetes.io/service-name=web
kubectl get pods -n prod -l app=web -o wide
# What class does the controller watch, and what did it log?
kubectl get ingressclass
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller --tail=60 | grep -i 'web\|default backend\|ingress'
# Reproduce with an explicit Host header against the controller
curl -i -H 'Host: app.example.com' http://<INGRESS_LB_IP>/
# For TLS / SNI
curl -ivk https://app.example.com/ --resolve app.example.com:443:<INGRESS_LB_IP>
Step-by-Step Resolution
-
Confirm the Ingress is picked up by the controller. If
describeshows noAddressand the controller log never mentions the Ingress, it is being ignored — almost always a class problem.kubectl get ingressclass kubectl get ingress web -n prod -o jsonpath='{.spec.ingressClassName}{"\n"}'Set
spec.ingressClassNameto the class the controller watches (commonlynginx). -
Check the host and path match the request. Make the rule’s
host:match theHostheader clients send (or removehost:for a catch-all), and verifypathType.- path: / pathType: Prefix # Prefix matches /, /api, /api/v1; Exact matches only "/" -
Verify the Service has endpoints. An empty
ENDPOINTScolumn means the controller has nothing to route to.kubectl get endpoints web -n prodNAME ENDPOINTS AGE web <none> 6mFix the Service selector/port to match the pods, and ensure the pods pass their readiness probe (only
Readypods become endpoints).kubectl get svc web -n prod -o jsonpath='{.spec.selector}{"\n"}' kubectl get pods -n prod --show-labels | grep web -
Put the Ingress in the Service’s namespace. ingress-nginx resolves the backend Service in the Ingress’s own namespace; move or duplicate the Ingress so both live together.
-
Fix TLS/SNI. For HTTPS, ensure a
tls:host and Secret exist for the requested host; an SNI miss falls through to the default backend.tls: - hosts: [app.example.com] secretName: app-tls -
Review rewrite-target. If you use
nginx.ingress.kubernetes.io/rewrite-target, confirm the capture group and path leave the upstream a route it serves. -
Verify the fix.
curl -i -H 'Host: app.example.com' http://<INGRESS_LB_IP>/
Prevention and Best Practices
- Always set
spec.ingressClassNameexplicitly and match it to the controller’s watched class; relying on the deprecatedkubernetes.io/ingress.classannotation is error-prone. - Keep each Ingress in the same namespace as the Service it targets — cross-namespace backends are not resolved.
- Gate Services behind readiness probes that reflect real readiness, so pods only become endpoints when they can serve traffic.
- Use
PrefixpathTypefor path-based routing unless you specifically needExact, and document anyrewrite-targetcapture groups. - Add synthetic checks that curl each public host/path through the LB and alert on
default backend - 404, catching mismatches before users do. - Standardize TLS host lists and Secrets per host so SNI always matches a configured server. See more in Kubernetes & Helm guides.
Related Errors
503 Service Temporarily Unavailablefrom ingress-nginx — a matched Ingress whose Service has endpoints that are all failing health checks.endpoints "web" not found/ empty endpoints — the selector/readiness sub-cause covered above.ImagePullBackOff— keeps backend pods from ever becomingReady, so endpoints stay empty; see the ImagePullBackOff guide.node NotReady— backend pods on aNotReadynode drop out of endpoints; see the node NotReady guide.
Frequently Asked Questions
How do I know the 404 is from ingress-nginx and not my app?
The body is literally default backend - 404 and the Server header is nginx with Content-Length: 21. An application 404 carries your app’s own page and server header. If you see the default backend text, the controller never reached your Service.
My Ingress exists but the controller ignores it — why?
The most common reason is an ingressClassName that does not match the class the controller watches. Run kubectl get ingressclass, compare it to the Ingress’s spec.ingressClassName, and check the controller logs — an ignored Ingress is never mentioned there and gets no Address.
The Ingress and Service look correct but I still get the default backend.
Check kubectl get endpoints <service>. If it shows <none>, the Service selector does not match any Ready pods, so the controller has no upstream and falls back to the default backend. Fix the selector/port or the pods’ readiness.
Why does curl to the IP work but the hostname returns the default backend?
Your rule has a host: that does not match the Host header the request carries. Test with curl -H 'Host: app.example.com'; if that works, fix DNS/the host value so real clients send the matching header, or remove host: for a catch-all rule.
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.