grpc/grpc-go · error

external processor returned compressed grpc message which is

Error message

external processor returned compressed grpc message which is not supported

What it means

grpc-go's extproc filter does not support receiving gRPC messages that are marked compressed by the external processor (ext_proc.go:1366). The StreamedBodyResponse.grpc_message_compressed flag must be false; otherwise the filter fails the stream because it cannot handle a compressed payload in this code path.

Source

Thrown at internal/xds/httpfilter/extproc/ext_proc.go:1367

			// 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
	}
	if err := cs.config.mutationRules.ApplyAdditions(mutation.GetSetHeaders(), md); err != nil {
		return err
	}
	return cs.config.mutationRules.ApplyRemovals(mutation.GetRemoveHeaders(), md)
}

// closeProcSend gracefully half-closes the external processor stream across the
// background send goroutine by pushing a nil sentinel onto procSendCh.
func (cs *clientStream) closeProcSend() {

View on GitHub (pinned to 03255a9237)

Solutions

  1. Set grpc_message_compressed = false on all StreamedBodyResponse messages from the extproc server.
  2. Decompress the chunk before placing it in StreamedBodyResponse so the flag can stay false.
  3. If compression is required end-to-end, configure it at the gRPC channel/compression level, not via the extproc flag.

Example fix

// before
streamedResp.GrpcMessageCompressed = true

// after
streamedResp.GrpcMessageCompressed = false
Defensive patterns

Strategy: validation

Validate before calling

// Server side: clear the flag before sending
if streamedResp.GetGrpcMessageCompressed() {
    streamedResp.GrpcMessageCompressed = false
}

Prevention

When it happens

Trigger: The extproc server sets StreamedBodyResponse.grpc_message_compressed = true on a body response.

Common situations: Server copies a compressed response directly into the chunk and flags it compressed; misunderstanding the contract where the extproc layer is expected to deliver uncompressed chunks for grpc-go to (re)compress itself.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/6de6bbfff7240dff. Report an issue: GitHub.