{"record":{"id":"cc10603ea274f6a4","repo":"grpc/grpc-go","slug":"security-configuration-on-the-server-side-does-not-cc1060","errorCode":null,"errorMessage":"security configuration on the server-side does not contain root certificate provider instance name, but require_client_cert field is set","messagePattern":"security configuration on the server-side does not contain root certificate provider instance name, but require_client_cert field is set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/xdsclient/xdsresource/unmarshal_lds.go","lineNumber":363,"sourceCode":"\t\treturn emptyFilterChain, fmt.Errorf(\"failed to unmarshal DownstreamTlsContext in LDS response: %v\", err)\n\t}\n\tif downstreamCtx.GetRequireSni().GetValue() {\n\t\treturn emptyFilterChain, fmt.Errorf(\"require_sni field set to true in DownstreamTlsContext message: %v\", downstreamCtx)\n\t}\n\tif downstreamCtx.GetOcspStaplePolicy() != v3tlspb.DownstreamTlsContext_LENIENT_STAPLING {\n\t\treturn emptyFilterChain, fmt.Errorf(\"ocsp_staple_policy field set to unsupported value in DownstreamTlsContext message: %v\", downstreamCtx)\n\t}\n\tif downstreamCtx.GetCommonTlsContext() == nil {\n\t\treturn emptyFilterChain, errors.New(\"DownstreamTlsContext in LDS response does not contain a CommonTlsContext\")\n\t}\n\tsc, err := securityConfigFromCommonTLSContext(downstreamCtx.GetCommonTlsContext(), true)\n\tif err != nil {\n\t\treturn emptyFilterChain, err\n\t}\n\tif sc != nil {\n\t\tsc.RequireClientCert = downstreamCtx.GetRequireClientCertificate().GetValue()\n\t\tif sc.RequireClientCert && sc.RootInstanceName == \"\" {\n\t\t\treturn emptyFilterChain, errors.New(\"security configuration on the server-side does not contain root certificate provider instance name, but require_client_cert field is set\")\n\t\t}\n\t\tfcc.SecurityCfg = sc\n\t}\n\treturn fcc, nil\n}\n\n// dstPrefixEntry wraps DestinationPrefixEntry to track build state.\ntype dstPrefixEntry struct {\n\tentry         DestinationPrefixEntry\n\trawBufferSeen bool\n}\n\nfunc buildFilterChainMap(fcs []*v3listenerpb.FilterChain) (NetworkFilterChainMap, error) {\n\tdstPrefixEntries := []*dstPrefixEntry{}\n\tfor _, fc := range fcs {\n\t\tfcMatch := fc.GetFilterChainMatch()\n\t\tif fcMatch.GetDestinationPort().GetValue() != 0 {\n\t\t\t// Destination port is the first match criteria and we do not","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/xdsclient/xdsresource/unmarshal_lds.go#L345-L381","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\n//   downstream_tls_context: { require_client_certificate: true, common_tls_context: { tls_certificate_provider_instance: { instance_name: \"default\" } } }\n// after\n//   downstream_tls_context: {\n//     require_client_certificate: true,\n//     common_tls_context: {\n//       tls_certificate_provider_instance: { instance_name: \"default\" },\n//       validation_context: { certificate_provider_instance: { instance_name: \"client-roots\" } }\n//     }\n//   }","handlingStrategy":"validation","validationCode":"// Ensure a server-side downstream TLS context with require_client_cert also has a validation context.\nfunc validateMutualTLS(dtls *envoy_tls_pb.DownstreamTlsContext) error {\n    if !dtls.GetRequireClientCertificate().GetValue() { return nil }\n    ctc := dtls.GetCommonTlsContext()\n    if ctc == nil { return errors.New(\"require_client_cert set but common_tls_context missing\") }\n    if ctc.GetValidationContext().GetCertificateProviderInstance().GetInstanceName() == \"\" &&\n       ctc.GetCombinedValidationContext().GetDefaultValidationContext().GetCertificateProviderInstance().GetInstanceName() == \"\" {\n        return errors.New(\"require_client_cert set but no root certificate provider instance name\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"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.","preventionTips":["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."],"tags":["xds","lds","tls","mtls","client-auth","control-plane","validation-context"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}