grpc/grpc-go · error
external processor unexpectedly sent request body when…
Error message
external processor unexpectedly sent request body when request body processing is disabled
What it means
Raised by recvFromProcServerLoop (ext_proc.go:1423) when the ext_proc server sends a request_body response but the configured requestBodyMode is modeSkip (NONE). Sending request body mutations the client never asked for is a protocol violation; failProcStream is called, which fails the RPC with codes.Internal unless failure_mode_allow bypasses it.
Solutions
- Make the ext_proc server honor the ProtocolConfiguration.request_body_mode the client sent and only return request_body when it is GRPC.
- Set request_body_mode to GRPC in the xDS config if body mutation is actually desired.
- Enable failure_mode_allow so the client bypasses ext_proc instead of failing the user RPC.
- Audit the server handler to ensure it does not emit request_body responses on the SKIP path.
Example fix
// before: server always returns request body regardless of negotiated mode
return &procpb.ProcessingResponse{Response: &procpb.ProcessingResponse_RequestBody{...}}, nil
// after: only return when the client advertised request body mode GRPC
if protocolCfg.GetRequestBodyMode() == procpb.BodySendMode_GRPC {
return &procpb.ProcessingResponse{Response: &procpb.ProcessingResponse_RequestBody{...}}, nil
}
return &procpb.ProcessingResponse{Response: &procpb.ProcessingResponse_RequestHeaders{...}}, nil Defensive patterns
Strategy: fallback
Validate before calling
// On the ext_proc SERVER: only emit request_body when the client negotiated GRPC.
func shouldEmitRequestBody(protocolCfg *procpb.ProtocolConfiguration) bool {
return protocolCfg.GetRequestBodyMode() == procpb.BodySendMode_GRPC
} Try / catch
// On the CLIENT: set failure_mode_allow so a server protocol violation bypasses
// ext_proc instead of failing the user RPC.
filter.failure_mode_allow = true
// Then optionally catch codes.Internal to surface/log ext_proc bypass.
if st, ok := status.FromError(err); ok && st.Code() == codes.Internal &&
strings.Contains(st.Message(), "unexpectedly sent request body") {
// ext_proc server violated the negotiated mode; investigate server-side
} Prevention
- Make the ext_proc server read ProtocolConfiguration.request_body_mode at stream open and skip request_body output when it is NONE.
- Keep server and xDS processing_mode in sync (deploy them together).
- Enable failure_mode_allow in production so a mode mismatch degrades rather than fails calls.
- Add a server-side integration test that runs against a SKIP config and asserts no request_body is sent.
When it happens
Trigger: Triggered when processing_mode.request_body_mode is NONE/SKIP yet the ext_proc server returns a ProcessingResponse with the request_body field set (ext_proc.go:1421).
Common situations: Server-side processing-mode mismatch (server assumes request body is enabled while the xDS config has NONE), shared/templated ext_proc handler that always echoes body mutations, or a control-plane config drift between what the server thinks and what the client advertised.
Related errors
- external processor unexpectedly sent response body when…
- external processor unexpectedly sent response headers when…
- external processor unexpectedly sent response trailers when…
- external processor returned invalid body mutation in body…
- external processor returned unexpected status
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/8235308050ca7265.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/httpfilter/extproc/ext_proc.go:1423
if err != nil {
cs.failProcStream(err)
return
}
if resp.GetRequestDrain() {
// Trigger the drain but continue receiving the drained messages until we
// get io.EOF.
cs.triggerBypass()
}
if resp.GetImmediateResponse() != nil {
cs.handleImmediateResponse(resp.GetImmediateResponse(), newStream, opts)
return
}
switch {
case resp.GetRequestBody() != nil:
if cs.config.processingModes.requestBodyMode == modeSkip {
cs.failProcStream(fmt.Errorf("external processor unexpectedly sent request body when request body processing is disabled"))
return
}
streamedResp, ok := cs.validateBodyResponse(resp.GetRequestBody())
if !ok {
return
}
if streamedResp.GetEndOfStream() {
cs.discardRequests.Store(true)
}
cs.mutatedReqBuffer.Put(streamedResp)
case resp.GetResponseBody() != nil:
if cs.config.processingModes.responseBodyMode == modeSkip {
cs.failProcStream(fmt.Errorf("external processor unexpectedly sent response body when response body processing is disabled"))
return
}
View on GitHub (pinned to 0c51461d27)