grpc/grpc-go · critical

extproc: failed to create channel to the external processor

Error message

extproc: failed to create channel to the external processor server %q: %v

What it means

Raised by BuildClientInterceptor when iextproc.CreateExtProcChannel(config.server) fails. The filter could not establish a gRPC client channel to the configured external processor server (the dial failed before any RPC), so the interceptor cannot be built and the filter is rejected for that target.

Source

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

	b, ok := base.(baseConfig)
	if !ok {
		return nil, fmt.Errorf("extproc: incorrect config type provided (%T): %v", base, base)
	}

	var ov overrideConfig
	if override != nil {
		ov, ok = override.(overrideConfig)
		if !ok {
			return nil, fmt.Errorf("extproc: incorrect override config type provided (%T): %v", override, override)
		}
	}

	config := newInterceptorConfig(b, ov)

	// Create a channel to the external processor server.
	cc, cancel, err := iextproc.CreateExtProcChannel(config.server)
	if err != nil {
		return nil, fmt.Errorf("extproc: failed to create channel to the external processor server %q: %v", config.server.TargetURI, err)
	}
	return &clientInterceptor{
		config:          config,
		procClient:      v3procservicegrpc.NewExternalProcessorClient(cc),
		closeClient:     cancel,
		metricsRecorder: cf.metricsRecorder,
		target:          cf.target,
	}, nil
}

type clientInterceptor struct {
	config          baseConfig
	procClient      v3procservicegrpc.ExternalProcessorClient
	closeClient     func() error
	metricsRecorder estats.MetricsRecorder
	target          string
}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Check the wrapped dial error (%v) — it distinguishes DNS failure, TLS failure, and connection refused.
  2. Verify config.server.TargetURI resolves and the ext-proc server is reachable (grpcurl / kubectl port-forward / telnet to the port).
  3. Fix TLS: ensure the CA bundle and SNI/override match the server certificate, or switch to plaintext for debugging.
  4. If transient, ensure the channel factory has retry/backoff and the LDS update is reprocessed once endpoints come back.

Example fix

// before: unreachable target
grpc_service:
  envoy_grpc:
    cluster_name: ext_proc_cluster   # cluster has 0 healthy endpoints

// after: target resolves to a live ext-proc server
grpc_service:
  envoy_grpc:
    cluster_name: ext_proc_cluster   # cluster backs a healthy Service+Deployment
Defensive patterns

Strategy: retry

Try / catch

// Channel/dial failures surface from BuildClientInterceptor as a wrapped error;
// retry by reprocessing the LDS resource once endpoints/TLS are fixed.
ci, err := cf.BuildClientInterceptor(base, ov)
if err != nil {
    if strings.Contains(err.Error(), "failed to create channel to the external processor server") {
        // transient: surface to xdsclient to retry on next update
    }
    return err
}

Prevention

When it happens

Trigger: Dialing config.server.TargetURI fails: DNS resolution error, no route to host, TLS handshake/cert verification failure, bad authority scheme, connection refused, or the channel factory rejecting the GRPCServiceConfig (e.g. invalid credentials).

Common situations: Ext-proc server pod is down or Service has no ready endpoints. TLS CA cert misconfigured or hostname mismatch. target_uri uses a scheme the resolver does not understand. Network policy/firewall blocking the port. Service mesh sidecar not injected so the authority is unreachable.

Related errors


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