grpc/grpc-go · error

UpstreamTlsContext in CDS response does not contain a Common

Error message

UpstreamTlsContext in CDS response does not contain a CommonTlsContext

What it means

Returned when unmarshalling a cluster's UpstreamTlsContext (unmarshal_cds.go:366-367) if the typed config parses but its common_tls_context field is nil. The CDS security handler requires a CommonTlsContext to derive a SecurityConfig; without it there is nothing to configure mTLS from, so the cluster resource is rejected (NACK).

Source

Thrown at internal/xds/xdsclient/xdsresource/unmarshal_cds.go:367

		tc = ts.GetTypedConfig()
		typeURL = tc.GetTypeUrl()
	}

	if name := ts.GetName(); name != transportSocketName {
		return nil, false, fmt.Errorf("transport_socket field has unexpected name: %s", name)
	}
	if typeURL != version.V3UpstreamTLSContextURL {
		return nil, false, fmt.Errorf("transport_socket missing typed_config or wrong type_url: %q", typeURL)
	}
	upstreamCtx := &v3tlspb.UpstreamTlsContext{}
	if err := proto.Unmarshal(tc.GetValue(), upstreamCtx); err != nil {
		return nil, false, fmt.Errorf("failed to unmarshal UpstreamTlsContext in CDS response: %v", err)
	}
	// The following fields from `UpstreamTlsContext` are ignored:
	// - allow_renegotiation
	// - max_session_keys
	if upstreamCtx.GetCommonTlsContext() == nil {
		return nil, false, errors.New("UpstreamTlsContext in CDS response does not contain a CommonTlsContext")
	}

	sc, err := securityConfigFromCommonTLSContext(upstreamCtx.GetCommonTlsContext(), false)
	if err != nil {
		return nil, false, err
	}
	// Set SNI related fields in SecurityConfig from UpstreamTlsContext if
	// `GRPC_EXPERIMENTAL_XDS_SNI` is enabled.
	if envconfig.XDSSNIEnabled {
		sc.SNI = upstreamCtx.GetSni()
		if len(sc.SNI) > maxSNILength {
			return nil, false, fmt.Errorf("SNI value %q in UpstreamTlsContext in CDS response exceeds max length of %d", sc.SNI, maxSNILength)
		}
		sc.UseAutoHostSNI = upstreamCtx.GetAutoHostSni()
		sc.AutoSNISANValidation = upstreamCtx.GetAutoSniSanValidation()
	}
	return sc, isHTTP11ProxyEnabled, nil
}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Fix the xDS server/fixture so UpstreamTlsContext.common_tls_context is populated with a valid CommonTlsContext (tls_certificate_certificate_provider / validation_context).
  2. If mTLS is not intended for that cluster, remove the transport_socket/UpstreamTlsContext entirely so no security block is parsed.
  3. Inspect the raw cluster resource and confirm common_tls_context is present and non-empty.

Example fix

// before
//   upstream_tls_context: { sni: "svc.example" }   // missing common_tls_context
// after
//   upstream_tls_context: {
//     common_tls_context: {
//       tls_certificate_certificate_provider_instance: { instance_name: "default", certificate_name: "default" },
//       validation_context: { ... }
//     }
//   }
Defensive patterns

Strategy: validation

Validate before calling

func upstreamTLSHasCommonCtx(uts *v3tlspb.UpstreamTlsContext) bool {
    return uts != nil && uts.GetCommonTlsContext() != nil
}

Type guard

func isCompleteUpstreamTLS(uts *v3tlspb.UpstreamTlsContext) bool {
    return upstreamTLSHasCommonCtx(uts)
}

Prevention

When it happens

Trigger: A CDS response provides a transport_socket with typed_config UpstreamTlsContext, but the UpstreamTlsContext message has no common_tls_context populated. The nil check at line 366 fires.

Common situations: Control plane sends a partial/incomplete UpstreamTlsContext (e.g. only sni set, no common_tls_context); a templating bug in the xDS server; a malformed bootstrap or test fixture.

Related errors


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