🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

Kubernetes HTTPRoute Not Working: Fix Accepted=False and 404 Errors

HTTPRoute created but traffic returns 404 or its status shows Accepted=False? Diagnose parentRefs, listeners, hostnames, ReferenceGrant, backend ports, and controller status step by step.

Shubham3 min read
Share:Tweet

An HTTPRoute can be accepted by the Kubernetes API and still route no traffic. kubectl apply only proves the object passed schema validation. It does not prove that a Gateway controller accepted the route, attached it to a listener, resolved its backend, or programmed the data plane.

Use this order to find the failure quickly.

Step 1: Read HTTPRoute Status First

bash
kubectl get httproute -A
kubectl describe httproute checkout -n app
kubectl get httproute checkout -n app -o yaml

Look under status.parents[].conditions:

yaml
status:
  parents:
  - conditions:
    - type: Accepted
      status: "False"
      reason: NoMatchingParent
    - type: ResolvedRefs
      status: "True"

Interpret the two important conditions separately:

  • Accepted=False: the route did not attach to the intended Gateway/listener.
  • ResolvedRefs=False: the route attached, but a referenced Service, port, Secret, or cross-namespace object is invalid or forbidden.

If no parent status appears, confirm that a controller is running and watches the route's GatewayClass.

Cause 1: Wrong parentRefs Name or Namespace

yaml
spec:
  parentRefs:
  - name: public-gateway
    namespace: gateway-system

Check the actual object:

bash
kubectl get gateway -A
kubectl get gateway public-gateway -n gateway-system

If namespace is omitted, parentRefs.name refers to a Gateway in the HTTPRoute's namespace. That is a common reason a cross-namespace route never attaches.

Cause 2: Listener Does Not Allow the Route

Inspect the Gateway:

bash
kubectl get gateway public-gateway -n gateway-system -o yaml

A listener can restrict namespaces:

yaml
listeners:
- name: https
  protocol: HTTPS
  port: 443
  allowedRoutes:
    namespaces:
      from: Selector
      selector:
        matchLabels:
          gateway-access: allowed

Fix the label or listener policy:

bash
kubectl label namespace app gateway-access=allowed

Also confirm that sectionName matches the listener name exactly:

yaml
parentRefs:
- name: public-gateway
  namespace: gateway-system
  sectionName: https

Cause 3: Hostname Does Not Intersect

Gateway listener:

yaml
hostname: "*.example.com"

HTTPRoute:

yaml
hostnames:
- api.internal.company.net

These hostnames do not intersect, so the route cannot attach to that listener. Align the route hostname and test with the correct Host header:

bash
curl -i --resolve api.example.com:443:$GATEWAY_IP https://api.example.com/

Testing the load-balancer IP without the expected hostname often produces a gateway 404 even when the route is healthy.

Cause 4: Cross-Namespace Backend Needs ReferenceGrant

Route in namespace app:

yaml
backendRefs:
- name: checkout
  namespace: services
  port: 8080

The target namespace must explicitly allow that reference:

yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-app-routes
  namespace: services
spec:
  from:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespace: app
  to:
  - group: ""
    kind: Service
    name: checkout

Without it, expect ResolvedRefs=False with a reason such as RefNotPermitted.

Cause 5: backendRefs Port Is Wrong

backendRefs.port must match the Service port, not necessarily the container port:

yaml
apiVersion: v1
kind: Service
metadata:
  name: checkout
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080

Correct route:

yaml
backendRefs:
- name: checkout
  port: 80

Verify endpoints too:

bash
kubectl get svc checkout -n app -o yaml
kubectl get endpointslice -n app -l kubernetes.io/service-name=checkout

An accepted route pointing to a Service with no ready endpoints usually produces 503, not 404.

Cause 6: GatewayClass or Controller Is Not Ready

bash
kubectl get gatewayclass
kubectl describe gatewayclass <class-name>
kubectl get pods -A | grep -E 'gateway|traefik|envoy|kgateway'

The class should show an accepted condition, the Gateway should be programmed, and its controller should have RBAC to watch Gateway API resources.

Fast Diagnostic Checklist

bash
kubectl get gatewayclass
kubectl get gateway -A
kubectl get httproute -A
kubectl describe httproute checkout -n app
kubectl get svc,endpointslice -n app
kubectl logs -n <controller-namespace> deploy/<controller> --since=15m

Read conditions before controller logs. Status reasons usually identify the configuration layer that failed.

Known-Good Minimal Route

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: checkout
  namespace: app
spec:
  parentRefs:
  - name: public-gateway
  hostnames:
  - checkout.example.com
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: checkout
      port: 80

Once Accepted=True and ResolvedRefs=True, test DNS/hostname, Gateway address, Service endpoints, and application health in that order.

Sources

  • /blog/how-to-set-up-kubernetes-gateway-api-2026
  • /blog/how-to-migrate-ingress-nginx-to-gateway-api-2026
  • /blog/kubernetes-ingress-503-service-unavailable-fix-2026
🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments