grpc/grpc-go · error
security configuration on the server-side does not contain…
Error message
security configuration on the server-side does not contain root certificate provider instance name, but require_client_cert field is set
What it means
Thrown during server-side filter chain processing: a DownstreamTlsContext set require_client_certificate=true but the resulting SecurityConfig has an empty RootInstanceName. To verify client certs the server needs a root/trust bundle to validate against; requesting client auth without it is contradictory, so grpc-go rejects the chain.
Solutions
- Add a validation_context (or combined_validation_context) with a non-empty certificate_provider_instance instance_name for the client root CA.
- Alternatively, set require_client_certificate=false if client auth is not actually required.
- Confirm the bootstrap certificate_providers defines the root provider name the control plane references for inbound mTLS.
Example fix
// before
// downstream_tls_context: { require_client_certificate: true, common_tls_context: { tls_certificate_provider_instance: { instance_name: "default" } } }
// after
// downstream_tls_context: {
// require_client_certificate: true,
// common_tls_context: {
// tls_certificate_provider_instance: { instance_name: "default" },
// validation_context: { certificate_provider_instance: { instance_name: "client-roots" } }
// }
// } Defensive patterns
Strategy: validation
Validate before calling
// Ensure a server-side downstream TLS context with require_client_cert also has a validation context.
func validateMutualTLS(dtls *envoy_tls_pb.DownstreamTlsContext) error {
if !dtls.GetRequireClientCertificate().GetValue() { return nil }
ctc := dtls.GetCommonTlsContext()
if ctc == nil { return errors.New("require_client_cert set but common_tls_context missing") }
if ctc.GetValidationContext().GetCertificateProviderInstance().GetInstanceName() == "" &&
ctc.GetCombinedValidationContext().GetDefaultValidationContext().GetCertificateProviderInstance().GetInstanceName() == "" {
return errors.New("require_client_cert set but no root certificate provider instance name")
}
return nil
} Try / catch
Catch in LDS watcher; alert ops that mTLS is half-configured. Fix in control plane by adding the root provider or disabling require_client_certificate.
Prevention
- Treat require_client_certificate as coupled with validation_context in policy checks.
- Document the bootstrap provider name used for client roots next to each mTLS listener.
- Run a pre-deploy script that asserts the root cert provider is registered in the bootstrap for that instance name.
When it happens
Trigger: LDS server filter chain sets downstream_tls_context.require_client_certificate=true, but the CommonTlsContext's validation context provides no root certificate provider instance name (and system roots are not configured for that path).
Common situations: Operator enabled mutual TLS (require client cert) but forgot to attach the client CA root provider. Asymmetric SDS setup where identity cert is provisioned but the validation/trust bundle is not. Istio PeerAuthentication set to MUTUAL_TLS without provisioning client root certs for the server.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- security configuration on the client-side does not contain…
- DownstreamTlsContext in LDS response does not contain a…
- security configuration on the server-side does not contain…
- filter missing name field
- multiple filter chains with overlapping matching rules are…
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/cc10603ea274f6a4.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/xdsclient/xdsresource/unmarshal_lds.go:363
return emptyFilterChain, fmt.Errorf("failed to unmarshal DownstreamTlsContext in LDS response: %v", err)
}
if downstreamCtx.GetRequireSni().GetValue() {
return emptyFilterChain, fmt.Errorf("require_sni field set to true in DownstreamTlsContext message: %v", downstreamCtx)
}
if downstreamCtx.GetOcspStaplePolicy() != v3tlspb.DownstreamTlsContext_LENIENT_STAPLING {
return emptyFilterChain, fmt.Errorf("ocsp_staple_policy field set to unsupported value in DownstreamTlsContext message: %v", downstreamCtx)
}
if downstreamCtx.GetCommonTlsContext() == nil {
return emptyFilterChain, errors.New("DownstreamTlsContext in LDS response does not contain a CommonTlsContext")
}
sc, err := securityConfigFromCommonTLSContext(downstreamCtx.GetCommonTlsContext(), true)
if err != nil {
return emptyFilterChain, err
}
if sc != nil {
sc.RequireClientCert = downstreamCtx.GetRequireClientCertificate().GetValue()
if sc.RequireClientCert && sc.RootInstanceName == "" {
return emptyFilterChain, errors.New("security configuration on the server-side does not contain root certificate provider instance name, but require_client_cert field is set")
}
fcc.SecurityCfg = sc
}
return fcc, nil
}
// dstPrefixEntry wraps DestinationPrefixEntry to track build state.
type dstPrefixEntry struct {
entry DestinationPrefixEntry
rawBufferSeen bool
}
func buildFilterChainMap(fcs []*v3listenerpb.FilterChain) (NetworkFilterChainMap, error) {
dstPrefixEntries := []*dstPrefixEntry{}
for _, fc := range fcs {
fcMatch := fc.GetFilterChainMatch()
if fcMatch.GetDestinationPort().GetValue() != 0 {
// Destination port is the first match criteria and we do notView on GitHub (pinned to 0c51461d27)