{"record":{"id":"4d4f323c97ddbb64","repo":"grpc/grpc-go","slug":"failed-to-create-a-stream-to-external-processor","errorCode":null,"errorMessage":"failed to create a stream to external processor: %v","messagePattern":"failed to create a stream to external processor: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/httpfilter/extproc/ext_proc.go","lineNumber":320,"sourceCode":"\t\tconfig:                 i.config,\n\t\tmetricsRecorder:        i.metricsRecorder,\n\t\ttarget:                 i.target,\n\t\tclientHeadersStartTime: timeNow(),\n\t\t// Construct request attributes once during stream initialization to capture\n\t\t// the original, unmutated request metadata and RPC info. For streaming\n\t\t// RPCs, where stream creation and message transmission are separable,\n\t\t// initializing attributes upfront avoids repeated protobuf construction on\n\t\t// subsequent SendMsg and RecvMsg calls.\n\t\treqAttrs: constructRequestAttributes(ri, outgoingMD, added, i.config.requestAttributes),\n\t}\n\n\t// In the ClientStream API, outgoing headers are sent immediately when the\n\t// stream is created. Because we need to send or mutate these headers before\n\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","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/httpfilter/extproc/ext_proc.go#L302-L338","documentation":"Raised during NewStream when i.procClient.Process(procCtx) returns an error — the channel exists but the bidirectional stream to the external processor could not be opened. This is an RPC-level (not dial-level) failure against the ext-proc server and is funneled through handleInitError, which honors failure_mode_allow.","triggerScenarios":"Process() RPC initiation fails: server returns UNAVAILABLE/PERMISSION_DENIED, transport closed mid-handshake, server-side stream limit hit, deadline exceeded on procCtx (server.Timeout), or context canceled before the stream was established.","commonSituations":"Ext-proc server up but rejecting streams (authz, mTLS). grpc_service.timeout too short so procCtx deadline fires at stream open. Server overloaded / refusing new streams. Transient network blip after channel became idle.","solutions":["Inspect the wrapped error (%v) for the gRPC status code — UNAVAILABLE points to transport, PERMISSION_DENIED to authz.","If transient, rely on the channel reconnecting and retry the RPC; consider raising grpc_service.timeout if the deadline is firing.","Set failure_mode_allow: true so handleInitError bypasses the processor and falls through to the dataplane stream instead of failing the RPC.","Verify server-side logs for why the Process stream was rejected."],"exampleFix":"// before: any stream-open failure kills the RPC\nfailure_mode_allow: false\n\n// after: tolerate ext-proc stream-open failures by bypassing\nfailure_mode_allow: true","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Stream-open errors honor failure_mode_allow via handleInitError.\n// Set failure_mode_allow:true so the user RPC falls through to the dataplane\n// instead of failing with codes.Internal.","preventionTips":["Set failure_mode_allow: true in the filter config to tolerate stream-open failures.","Tune grpc_service.timeout so the procCtx deadline does not fire at open.","Keep the ext-proc server able to accept new streams (concurrency limits, authz)."],"tags":["extproc","network","grpc-stream","runtime","failure-mode-allow"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}