grpc/grpc-go · error
external processor returned unexpected status %v for request
Error message
external processor returned unexpected status %v for request headers, expected %v
What it means
After the request-headers handshake message is received, the filter verifies its CommonResponse status is CONTINUE (ext_proc.go:1548). A non-CONTINUE status is treated as an error during header processing and, depending on failure_mode_allow, either bypasses the processor or fails the RPC.
Source
Thrown at internal/xds/httpfilter/extproc/ext_proc.go:1549
return false
}
if resp.GetRequestDrain() {
cs.triggerBypass()
}
if resp.GetImmediateResponse() != nil {
cs.handleImmediateResponse(resp.GetImmediateResponse(), newStream, opts)
return false
}
header := resp.GetRequestHeaders()
if header == nil {
err := fmt.Errorf("external processor returned an unexpected message type %T, expected request headers response", resp.GetResponse())
cs.handleHeaderError(err, newStream, opts)
return false
}
// Check if status in header response is CONTINUE; if not, fail the stream.
if status := header.GetResponse().GetStatus(); status != v3procservicepb.CommonResponse_CONTINUE {
cs.handleHeaderError(fmt.Errorf("external processor returned unexpected status %v for request headers, expected %v", status, v3procservicepb.CommonResponse_CONTINUE), newStream, opts)
return false
}
// Mutate the outgoing headers with additions and removals received from the
// external processor.
outgoingMD, _ := metadata.FromOutgoingContext(ctx)
if outgoingMD == nil {
outgoingMD = metadata.MD{}
}
if err = cs.applyMutations(header.GetResponse().GetHeaderMutation(), outgoingMD); err != nil {
cs.handleHeaderError(err, newStream, opts)
return false
}
dataplaneCtx := metadata.NewOutgoingContext(ctx, outgoingMD)
if err = cs.createDataplaneStream(dataplaneCtx, newStream, opts); err != nil {
return false
}
return true
}View on GitHub (pinned to 03255a9237)
Solutions
- Set response.status = CONTINUE on the request_headers response from the extproc server.
- If the server wants to reject, send an ImmediateResponse instead of a non-CONTINUE header status.
- Set failure_mode_allow=true in config so header errors bypass cleanly while the server is fixed.
Example fix
// before hdrResp.Response.Status = procservicepb.CommonResponse(0) // unset != CONTINUE // after hdrResp.Response.Status = procservicepb.CommonResponse_CONTINUE
Defensive patterns
Strategy: fallback
Validate before calling
// Server side
if hdrResp.GetResponse().GetStatus() != procservicepb.CommonResponse_CONTINUE {
hdrResp.Response.Status = procservicepb.CommonResponse_CONTINUE
} Prevention
- Always set Status=CONTINUE on the request_headers response.
- Use ImmediateResponse to reject rather than a non-CONTINUE status.
- Set failure_mode_allow during development.
When it happens
Trigger: The extproc server returns a request_headers response whose status is not CONTINUE (unset, or some other enum value).
Common situations: Server constructs the headers response without setting Status; server attempts to signal an error through status instead of using ImmediateResponse; protobuf default-value confusion (zero status is not CONTINUE).
Related errors
- external processor unexpectedly sent duplicate response trai
- external processor returned unexpected status %v for body re
- external processor returned invalid body mutation in body re
- external processor returned compressed grpc message which is
- external processor returned an unexpected message type %T, e
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/1a7d18e01cc5fbe8.
Report an issue: GitHub.