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
handleImmediateResponse (ext_proc.go:1742) fires when the external processor sends an immediate_response while config.disableImmediateResponse is true. The filter is configured to forbid immediate responses, so it fails the stream (or bypasses it per failureModeAllow) instead of honoring the abort.
Solutions
- If immediate responses are intended, remove disableImmediateResponse from the extproc filter config in the xDS Listener/Route.
- If immediate responses must stay disabled, fix the external processor to never send them (use header mutation + CONTINUE instead).
- Reconcile the control-plane config and server contract before redeploying.
Example fix
// before (xDS filter config) disable_immediate_response: true // after // (field removed or set false) disable_immediate_response: false
Defensive patterns
Strategy: validation
Validate before calling
// Before deploying, reconcile filter config and server contract
if filterConfig.DisableImmediateResponse && serverSendsImmediateResponses {
return errors.New("extproc: immediate responses disabled in config but server emits them")
} Try / catch
// Client-side: surfaces as codes.Internal.
if st, ok := status.FromError(err); ok && strings.Contains(st.Message(), "immediate responses are disabled") {
// remove disableImmediateResponse from config or stop sending immediate responses
} Prevention
- Document the disableImmediateResponse flag at the control-plane and server teams.
- If the server needs to reject requests, agree on whether to use immediate_response or header mutation + CONTINUE.
When it happens
Trigger: Client filter config sets disableImmediateResponse=true and the external processor returns a ProcessingResponse with the immediate_response variant set.
Common situations: Operator disabled immediate responses for safety/latency reasons, but the external processor still emits them (e.g., for auth rejection). Mismatch between control-plane filter config and server behavior.
Related errors
- external processor returned an unexpected message type %T…
- external processor returned compressed grpc message which…
- external processor returned unexpected status
- extproc: empty grpc_service provided in config
- extproc: error parsing config
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/d735803f50196e5b.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/httpfilter/extproc/ext_proc.go:1743
// 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 0c51461d27)