grpc/grpc-go · error
DownstreamTlsContext in LDS response does not contain a…
Error message
DownstreamTlsContext in LDS response does not contain a CommonTlsContext
What it means
Thrown when validating a DownstreamTlsContext attached to a server-side filter chain's transport socket: the typed_config parsed successfully into a DownstreamTlsContext message, but its common_tls_context field is nil. A DownstreamTlsContext without a CommonTlsContext has no certificate material to negotiate, so grpc-go rejects the filter chain.
Solutions
- Populate common_tls_context inside the DownstreamTlsContext (at minimum, an identity certificate provider).
- If TLS is not intended, remove the transport_socket block from the filter chain entirely so grpc-go uses plaintext.
- Validate the LDS resource with protoc and require common_tls_context != nil whenever DownstreamTlsContext is used.
Example fix
// before
// transport_socket: { typed_config: { @type: "...DownstreamTlsContext", require_client_certificate: true } }
// after
// transport_socket: { typed_config: {
// @type: "...DownstreamTlsContext",
// common_tls_context: { tls_certificate_provider_instance: { instance_name: "default" } }
// } } Defensive patterns
Strategy: validation
Try / catch
Handle in the LDS watcher callback. The error comes from filter-chain security parsing; log the listener name and the offending filter chain name (if available). The fix is in the control plane: either populate common_tls_context or remove the transport_socket.
Prevention
- Policy-check LDS resources: any DownstreamTlsContext must carry a non-nil common_tls_context.
- In your xDS server, refuse to serve a downstream TLS context without common_tls_context.
- Integration-test server-side LDS resources end-to-end against grpc-go before rollout.
When it happens
Trigger: LDS FilterChain transport_socket typed_config is DownstreamTlsContext but the common_tls_context oneof/field is unset. Happens when a control plane emits a downstream TLS context skeleton (e.g. only setting require_client_certificate) but forgets the common_tls_context.
Common situations: Partial TLS config emitted during control-plane migration. Istio/equivalent resource where the server cert SDS reference is omitted. A user disabled TLS by removing common_tls_context but left the downstream_tls_context wrapper in place.
Related errors
- filter missing name field
- security configuration on the server-side does not contain…
- multiple filter chains with overlapping matching rules are…
- security configuration on the client-side does not contain…
- security configuration on the server-side does not contain…
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/1d62a49b5910c179.
Report an issue: GitHub.
Appendix: source
Thrown at internal/xds/xdsclient/xdsresource/unmarshal_lds.go:354
if name := ts.GetName(); name != transportSocketName {
return emptyFilterChain, fmt.Errorf("transport_socket field has unexpected name: %s", name)
}
tc := ts.GetTypedConfig()
if typeURL := tc.GetTypeUrl(); typeURL != version.V3DownstreamTLSContextURL {
return emptyFilterChain, fmt.Errorf("transport_socket missing typed_config or wrong type_url: %q", typeURL)
}
downstreamCtx := &v3tlspb.DownstreamTlsContext{}
if err := proto.Unmarshal(tc.GetValue(), downstreamCtx); err != nil {
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 DestinationPrefixEntryView on GitHub (pinned to 0c51461d27)