Skip to content

BackendTrafficPolicy status does not report missing targetRef and leaves stale observedGeneration #8926

@zhaohuabing

Description

@zhaohuabing

Description

When a BackendTrafficPolicy in Envoy Gateway v1.8.0-rc.1 is updated to reference a nonexistent HTTPRoute, the policy status does not clearly report the invalid attachment.

Instead:

  • the policy continues to show Accepted=True
  • no condition indicates that the target route is missing / unresolved
  • status.ancestors[*].conditions[*].observedGeneration remains stale and does not match the latest metadata.generation

This makes it hard to tell from status whether the policy is actually attached to a valid target.

Reproducer

  1. Create a kind cluster
  2. Install Envoy Gateway v1.8.0-rc.1
  3. Apply the quickstart example
  4. Create a valid BackendTrafficPolicy targeting the quickstart HTTPRoute
  5. Update the policy so targetRefs.name points to a nonexistent route

Environment

  • Envoy Gateway version: v1.8.0-rc.1
  • Install method: Helm chart oci://docker.io/envoyproxy/gateway-helm
  • Gateway image: docker.io/envoyproxy/gateway:v1.8.0-rc.1

Initial valid policy

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
  name: quickstart-btp
  namespace: default
spec:
  targetRefs:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: backend
  retry:
    numRetries: 3
    perRetry:
      backOff:
        baseInterval: 100ms
        maxInterval: 1s
      timeout: 250ms
    retryOn:
      triggers:
      - 5xx
      - gateway-error
      - connect-failure

Updated invalid policy

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
  name: quickstart-btp
  namespace: default
spec:
  targetRefs:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: does-not-exist
  retry:
    numRetries: 3
    perRetry:
      backOff:
        baseInterval: 100ms
        maxInterval: 1s
      timeout: 250ms
    retryOn:
      triggers:
      - 5xx
      - gateway-error
      - connect-failure

Observed behavior

The target route does not exist:

kubectl -n default get httproute does-not-exist
# Error from server (NotFound): httproutes.gateway.networking.k8s.io "does-not-exist" not found

But the policy status remains:

status:
  ancestors:
  - ancestorRef:
      group: gateway.networking.k8s.io
      kind: Gateway
      name: eg
      namespace: default
    conditions:
    - type: Accepted
      status: "True"
      reason: Accepted
      message: Policy has been accepted.
      observedGeneration: 3

while:

metadata:
  generation: 4

So:

  • Accepted=True is still reported
  • no condition indicates unresolved or missing target
  • observedGeneration is stale (3 vs current generation 4)

Expected behavior

I’d expect one of the following:

  • a condition indicating the referenced target does not exist / cannot be resolved
  • attachment status that clearly shows the policy is not applied to any valid target
  • observedGeneration updated to the latest generation even if attachment fails

At minimum, status should make it obvious that the policy is not effectively attached.

Why this matters

From the user perspective, the current status is misleading:

  • the object is syntactically valid, so Accepted=True makes sense at one level
  • but there is no visible status signal that the targetRef is broken
  • stale observedGeneration adds more ambiguity about whether reconciliation completed

This makes debugging policy attachment failures much harder.

I believe this also happens to other xPolicies and Gateway API resources.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions