When a PipelinePolicy with an add_deny action (terminal: true) is used alongside an AuthPolicy (with or without RateLimitPolicy) on the same route, and the deny predicate matches:
- Duplicate traces — a single HTTP request produces two separate traces
- Duplicate Authorino call — the auth gRPC call is made twice for one request, adding unnecessary latency and load
- Missing
grpc_response span — the deny action interrupts the pipeline before the auth gRPC response is processed
When only RateLimitPolicy + PipelinePolicy (no AuthPolicy)
- No duplicate traces — only one trace per request
- Missing
grpc_response span still present — the deny action still interrupts the pending rate limit gRPC call before its response arrives
Root cause
The terminal deny action calls Envoy's send_local_response(403) before pending gRPC responses arrive. This causes the missing grpc_response span in all cases. The duplicate trace specifically requires the auth action — the auth service's response-phase callback chain causes Envoy to re-invoke the wasm filter, triggering a full pipeline re-execution with a second Authorino call.
Reproduction matrix
| Policy combination |
Deny matches |
Duplicate trace |
Missing grpc_response |
| PipelinePolicy alone |
yes |
no |
yes |
| RateLimitPolicy + PipelinePolicy |
yes |
no |
yes |
| AuthPolicy + PipelinePolicy |
yes |
yes |
yes |
| AuthPolicy + RateLimitPolicy + PipelinePolicy |
yes |
yes |
yes |
| Any combination |
no (200) |
no |
no |
Does NOT happen when
add_fail is used instead of add_deny
- The deny predicate does not match (request returns 200)
- No AuthPolicy is involved (duplication specifically)
Evidence
Two Jaeger trace JSONs from a single curl request:
- Different trace IDs and request IDs
- Same action set hash
- ~17ms apart
- Both contain auth gRPC call to Authorino
- Neither contains a
grpc_response span
When a PipelinePolicy with an
add_denyaction (terminal: true) is used alongside an AuthPolicy (with or without RateLimitPolicy) on the same route, and the deny predicate matches:grpc_responsespan — the deny action interrupts the pipeline before the auth gRPC response is processedWhen only RateLimitPolicy + PipelinePolicy (no AuthPolicy)
grpc_responsespan still present — the deny action still interrupts the pending rate limit gRPC call before its response arrivesRoot cause
The terminal deny action calls Envoy's
send_local_response(403)before pending gRPC responses arrive. This causes the missinggrpc_responsespan in all cases. The duplicate trace specifically requires the auth action — the auth service's response-phase callback chain causes Envoy to re-invoke the wasm filter, triggering a full pipeline re-execution with a second Authorino call.Reproduction matrix
grpc_responseDoes NOT happen when
add_failis used instead ofadd_denyEvidence
Two Jaeger trace JSONs from a single curl request:
grpc_responsespan