Envoy Gateway Status and Debugging Handbook: What Accepted, ResolvedRefs, and Programmed Actually Mean
The most dreadful engineering scenario isn't an error message — it's:
You applied the YAML, kubectl apply succeeded, but traffic still isn't flowing.
If you only stare at spec at this point, you'll start feeling like you're reading tea leaves.
The real diagnostic information in Gateway API lives in status.
This post has one goal: give you the shortest possible debugging path. When a Gateway, HTTPRoute, or Listener isn't taking effect, you'll know where to look first — instead of immediately questioning whether the universe makes sense.
Start Here: Debug by Reading status, Not by Changing spec
The most useful commands:
kubectl get gateway -A
kubectl get httproute -A
kubectl get grpcroute -A
kubectl describe gateway <name>
kubectl describe httproute <name>
kubectl get gateway <name> -o yaml
kubectl get httproute <name> -o yamlThe point isn't to re-read the YAML a hundred more times — it's to check whether the controller actually accepted your config.
Think of status as an exam grade sheet:
specis the answer you submittedstatusis the system's graded result
Only looking at what you submitted, never checking the grade — that's just emotional comfort, not debugging.
Three Most Important Conditions: Master These and You're Covered
Accepted
This typically indicates whether the resource was accepted by its parent. For a route, it usually means:
- Whether it successfully attached to the intended Gateway/listener
- Whether the rules have any obvious conflicts or invalid configuration
If Accepted is False, first suspect:
parentRefspointing to the wrong Gateway or listener- Hostname/listener conditions not matching
- The listener rejecting this type of route
allowedRoutesblocking you
ResolvedRefs
This indicates whether referenced objects within the resource were successfully resolved. For example:
- Does the
Servicereferenced inbackendRefsexist? - Can the
SecretincertificateRefsbe legally referenced? - Is
ReferenceGrantproperly configured for cross-namespace references?
This condition is extremely useful. Many config failures aren't about wrong routing logic — they're about referenced things that simply don't exist, or that you don't have permission to access.
Programmed
This typically indicates whether config was actually applied at the implementation layer. Think of it as:
- The controller accepted the config
- And pushed it into the data plane or infrastructure
If Accepted is already True but traffic still isn't flowing, this is when checking Programmed, Gateway address, listener status, and underlying Envoy resources becomes worthwhile.
💡 Different resources may expose different sets of conditions, but
Accepted,ResolvedRefs, andProgrammedare the first group to build intuition about.
Shortest Debugging Flow: This Order Usually Works
Step 1: Check Whether the Gateway Is Actually Running
kubectl get gateway -A
kubectl get gateway eg -o yamlVerify:
- Does
status.addresseshave a value? - Are any listener conditions abnormal?
- Do listener hostname/protocol/port match what you expect?
If the Gateway has no address, even the most beautiful route YAML is just creative writing.
Step 2: Check Whether the Route Attached Successfully
kubectl get httproute -A
kubectl get httproute app-route -o yamlPrioritize:
status.parentsAcceptedResolvedRefsobservedGeneration
observedGeneration is worth watching.
If it hasn't caught up to metadata.generation, the controller may not have processed your latest config version yet.
Step 3: Check Whether Referenced Resources Actually Exist
This step is skipped more often than any other:
kubectl get svc -A
kubectl get secret -A
kubectl get referencegrant -ACommon problems:
- Backend service name is wrong
- Port is wrong
- Secret isn't in the namespace you think
- Cross-namespace reference is missing
ReferenceGrant
If ResolvedRefs is False, trace it along this path.
Step 4: Check the Data Plane and Controller
If Gateway and Route statuses both look roughly correct but traffic still isn't flowing, look deeper:
kubectl get pods -n envoy-gateway-system
kubectl logs -n envoy-gateway-system deployment/envoy-gatewayAt this point you're not debugging "was the rule accepted" — you're checking whether the control plane and data plane are working normally.
If you have egctl installed, it can help you inspect status quickly.
But even without it, kubectl get/describe -o yaml can resolve most problems.
Four Most Common Failure Patterns
1. Route Is Correct, But Didn't Attach to the Intended Listener
Symptoms:
- YAML looks right
- But traffic isn't hitting the rule
Check:
parentRefs.nameparentRefs.sectionName- Whether the Gateway listener name matches exactly
In multi-listener setups, one typo in sectionName is enough to waste an entire debugging session.
2. Accepted Succeeds, but ResolvedRefs Fails
This usually means the logic can attach, but something that's referenced has a problem. Most common causes:
- Backend Service doesn't exist
- Secret name is wrong
- Cross-namespace reference without authorization
The most frustrating thing about this type of failure is it looks like you're almost there — but it's actually stuck at the reference layer.
3. Gateway Has Listeners but No Expected Address
This frequently appears in local clusters or environments without a LoadBalancer implementation.
It's not that Gateway API is broken — the underlying infrastructure simply isn't provisioning an external address.
Options:
- Check whether the cluster has
LoadBalancercapability - Use
port-forwardto validate the routing path
4. YAML Took Effect, But Requests Return 404 / 503
At this point it's usually not a single wrong field — it's a broken chain somewhere:
- Wrong Host header
- Path not matching any rule
- Backend Pod is unhealthy
- Service selector isn't selecting any Pods
Ingress issues sometimes look like a proxy failure, but the backend simply wasn't ready. Don't blame everything on the proxy layer — it has enough on its plate.
One-Line Summary
The most effective way to debug Gateway API isn't constantly changing YAML — it's learning to read status.
Accepted tells you if the order was picked up. ResolvedRefs tells you if the references resolved. Programmed tells you if the config was actually applied. Examine these three layers separately and troubleshooting speed increases dramatically.
Next Step
This completes the 10-post Envoy Gateway series. If you want to revisit the full map of the series: