{"record":{"id":"695dc2e5c5800b45","repo":"grpc/grpc-go","slug":"failed-to-send-client-headers-to-external-processo","errorCode":null,"errorMessage":"failed to send client headers to external processor server: %v","messagePattern":"failed to send client headers to external processor server: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/httpfilter/extproc/ext_proc.go","lineNumber":334,"sourceCode":"\t// they go over the wire, we must establish the ext_proc stream now rather\n\t// than deferring it.\n\tvar err error\n\tif csCommon.procStream, err = i.procClient.Process(procCtx); err != nil {\n\t\treturn csCommon.handleInitError(fmt.Errorf(\"failed to create a stream to external processor: %v\", err), newStream, opts...)\n\t}\n\n\t// Observability mode.\n\tif i.config.observabilityMode {\n\t\tocs := &observabilityClientStream{\n\t\t\tcommonStream: csCommon,\n\t\t\tprocRecvDone: make(chan struct{}),\n\t\t}\n\n\t\t// If the request header processing mode is set to \"Send\", forward the\n\t\t// headers to the external processor server.\n\t\tif i.config.processingModes.requestHeaderMode == modeSend {\n\t\t\tif err = ocs.sendToProcessor(ocs.requestHeaders(outgoingMD, added)); err != nil {\n\t\t\t\treturn ocs.handleInitError(fmt.Errorf(\"failed to send client headers to external processor server: %v\", err), newStream, opts...)\n\t\t\t}\n\t\t}\n\n\t\t// Defer the closing of ext proc stream by the defined defferred close\n\t\t// timeout to allow the server to read all messages from the proc stream.\n\t\tonFinishFunc := func(error) {\n\t\t\ttime.AfterFunc(ocs.config.deferredCloseTimeout, ocs.procCancel)\n\t\t}\n\t\tnewOpts := append(opts, grpc.OnFinish(onFinishFunc))\n\n\t\tif ocs.dataplaneStream, err = newStream(ocs.ctx, newOpts...); err != nil {\n\t\t\tocs.cancel()\n\t\t\treturn nil, err\n\t\t}\n\t\tocs.recordMetric(clientHeadersDurationMetric, timeSince(ocs.clientHeadersStartTime).Seconds())\n\t\t// Start background goroutine to receive any messages from the external\n\t\t// processor server and discard them.\n\t\tgo ocs.discardProcessorResponsesLoop()","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/httpfilter/extproc/ext_proc.go#L316-L352","documentation":"Raised in observability mode when sendToProcessor(requestHeaders) fails on the freshly opened proc stream. The stream was established but the very first message (client request headers) could not be sent, and the error is routed through handleInitError.","triggerScenarios":"Observability mode is on, requestHeaderMode == modeSend, and procStream.Send of the requestHeaders ProcessingRequest fails — e.g. the server RST_STREAM'd immediately, transport went away, or context was canceled before the send completed.","commonSituations":"Server closes the proc stream as soon as it opens (misconfigured observability mode, version skew on the ProcessingRequest schema). Network reset after the initial handshake. procCtx canceled because the parent RPC context was canceled.","solutions":["Check server logs for why it tore down the stream right after Process() opened.","Ensure the external processor supports observability mode and the ProcessingRequest schema version the client sends.","Enable failure_mode_allow so handleInitError falls through to the dataplane stream instead of failing the user RPC.","If request-header sending is not actually needed, set request_header_mode to SKIP for the observability path."],"exampleFix":"// before\nobservability_mode: true\nrequest_header_mode: SEND   # server RSTs on first send\nfailure_mode_allow: false\n\n// after\nobservability_mode: true\nrequest_header_mode: SEND\nfailure_mode_allow: true","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Observability-mode send failures also go through handleInitError and respect\n// failure_mode_allow. Enable it to bypass rather than fail the user RPC.","preventionTips":["Ensure the server supports observability mode and the client's ProcessingRequest schema.","Set failure_mode_allow: true to tolerate initial-send failures.","If headers are not needed in observability mode, set request_header_mode: SKIP."],"tags":["extproc","observability","network","grpc-stream","runtime"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}