grpc/grpc-go · error

external processor sent an immediate response but immediate

Error message

external processor sent an immediate response but immediate responses are disabled in configuration

What it means

The extproc filter can be configured to disable immediate responses (disableImmediateResponse). If the server then sends a ProcessingResponse with an ImmediateResponse set, the filter cannot honor it and treats it as an error (ext_proc.go:1570), failing or bypassing the stream.

Source

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

	// 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
}

func (cs *clientStream) handleImmediateResponse(imm *v3procservicepb.ImmediateResponse, newStream func(context.Context, ...grpc.CallOption) (grpc.ClientStream, error), opts []grpc.CallOption) {
	if cs.config.disableImmediateResponse {
		err := fmt.Errorf("external processor sent an immediate response but immediate responses are disabled in configuration")
		if cs.dataplaneStream == nil {
			cs.handleHeaderError(err, newStream, opts)
		} else {
			cs.failProcStream(err)
		}
		return
	}

	statusCode := codes.Internal
	if imm.GetGrpcStatus() != nil {
		statusCode = codes.Code(imm.GetGrpcStatus().GetStatus())
		if statusCode > codes.Code(16) {
			statusCode = codes.Unknown
		}
	}
	err := status.Error(statusCode, imm.GetDetails())

	if cs.trailerSent.Load() {

View on GitHub (pinned to 03255a9237)

Solutions

  1. Align configuration and server behavior: either set disable_immediate_response=false in the extproc filter config, or stop the server from sending ImmediateResponse messages.
  2. Roll the extproc server to a version that respects the negotiated 'no immediate responses' contract.
  3. While migrating, set failure_mode_allow=true to avoid failing RPCs.

Example fix

// before: config disables immediate responses, server sends one
filterConfig.DisableImmediateResponse = true
// server: stream.Send(&procservicepb.ProcessingResponse{Response: &procservicepb.ProcessingResponse_ImmediateResponse{...}})

// after: allow immediate responses, or have the server avoid them
filterConfig.DisableImmediateResponse = false
Defensive patterns

Strategy: validation

Validate before calling

// Before enabling the filter, ensure config and server agree on immediate responses
if serverMaySendImmediateResponse {
    filterConfig.DisableImmediateResponse = false
}

Prevention

When it happens

Trigger: xDS extproc config sets disable_immediate_response = true, and the external processor sends a ProcessingResponse whose immediate_response field is populated.

Common situations: Operator enabled disable_immediate_response for safety/forward-compat while the deployed server still emits immediate responses; mismatch between the negotiated contract and server behavior; copy-pasted filter config from another environment.

Related errors


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