Envoy Gateway Status and Debugging Handbook: What Accepted, ResolvedRefs, and Programmed Actually Mean

6 min read

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 yaml

The 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:

  • spec is the answer you submitted
  • status is 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:

  • parentRefs pointing to the wrong Gateway or listener
  • Hostname/listener conditions not matching
  • The listener rejecting this type of route
  • allowedRoutes blocking you

ResolvedRefs

This indicates whether referenced objects within the resource were successfully resolved. For example:

  • Does the Service referenced in backendRefs exist?
  • Can the Secret in certificateRefs be legally referenced?
  • Is ReferenceGrant properly 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, and Programmed are 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 yaml

Verify:

  • Does status.addresses have 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 yaml

Prioritize:

  • status.parents
  • Accepted
  • ResolvedRefs
  • observedGeneration

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 -A

Common 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-gateway

At 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.name
  • parentRefs.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 LoadBalancer capability
  • Use port-forward to 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:

👉 Series Overview