grpc/grpc-go · error
external processor returned unexpected status %v for body re
Error message
external processor returned unexpected status %v for body response, expected %v
What it means
When validating a body response from the extproc server, the filter requires the CommonResponse status to be CONTINUE (ext_proc.go:1357). Any other status value means the server is not cleanly continuing the stream; the filter refuses to apply the body mutation and fails the proc stream.
Source
Thrown at internal/xds/httpfilter/extproc/ext_proc.go:1358
if cs.responseTrailerReady.HasFired() {
cs.failProcStream(fmt.Errorf("external processor unexpectedly sent duplicate response trailers after response trailers were already processed"))
return
}
trailer := resp.GetResponseTrailers()
if err = cs.applyMutations(trailer.GetHeaderMutation(), cs.responseTrailers); err != nil {
cs.failProcStream(err)
return
}
// Signal that the response trailer is modified and ready to be sent to
// the client.
cs.fireResponseTrailerReady()
}
}
}
func (cs *clientStream) validateBodyResponse(bodyResp *v3procservicepb.BodyResponse) (*v3procservicepb.StreamedBodyResponse, bool) {
if status := bodyResp.GetResponse().GetStatus(); status != v3procservicepb.CommonResponse_CONTINUE {
cs.failProcStream(fmt.Errorf("external processor returned unexpected status %v for body response, expected %v", status, v3procservicepb.CommonResponse_CONTINUE))
return nil, false
}
streamedResp := bodyResp.GetResponse().GetBodyMutation().GetStreamedResponse()
if streamedResp == nil {
cs.failProcStream(fmt.Errorf("external processor returned invalid body mutation in body response"))
return nil, false
}
if streamedResp.GetGrpcMessageCompressed() {
cs.failProcStream(fmt.Errorf("external processor returned compressed grpc message which is not supported"))
return nil, false
}
return streamedResp, true
}
func (cs *clientStream) applyMutations(mutation *v3procservicepb.HeaderMutation, md metadata.MD) error {
if mutation == nil {
return nil
}View on GitHub (pinned to 03255a9237)
Solutions
- Ensure the extproc server sets response.status = CONTINUE on every body ProcessingResponse it sends.
- If the server intends to reject, it should use an ImmediateResponse rather than a non-CONTINUE body status.
- Enable failure_mode_allow to tolerate the server error while debugging.
Example fix
// before bodyResp.Response.Status = procservicepb.CommonResponse_REPLY // after bodyResp.Response.Status = procservicepb.CommonResponse_CONTINUE
Defensive patterns
Strategy: fallback
Validate before calling
// Server side: assert before sending
if bodyResp.GetResponse().GetStatus() != procservicepb.CommonResponse_CONTINUE {
bodyResp.Response.Status = procservicepb.CommonResponse_CONTINUE
} Prevention
- Always set Status=CONTINUE on body responses in the extproc server.
- Use ImmediateResponse, not a non-CONTINUE status, to reject.
- Set failure_mode_allow during server development.
When it happens
Trigger: The external processor returns a ProcessingResponse with a body response whose CommonResponse.Status is anything other than CONTINUE (e.g. an unset/zero status or a custom enum value).
Common situations: Extproc server sets status incorrectly on body messages; server code path that constructs body responses without setting Status=CONTINUE; protobuf version drift exposing a new status enum value the client rejects.
Related errors
- external processor unexpectedly sent duplicate response trai
- 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
- external processor returned unexpected status %v for request
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/159c2b73c098cb33.
Report an issue: GitHub.