{"record":{"id":"dd5ada42beba4a4d","repo":"grpc/grpc-java","slug":"common-tls-context-is-required-in-upstream-tls-con","errorCode":null,"errorMessage":"common-tls-context is required in upstream-tls-context","messagePattern":"common-tls-context is required in upstream-tls-context","errorType":"validation","errorClass":"ResourceInvalidException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/XdsClusterResource.java","lineNumber":442,"sourceCode":"\n    return outlierDetection;\n  }\n\n  static boolean hasNegativeValues(Duration duration) {\n    return duration.getSeconds() < 0 || duration.getNanos() < 0;\n  }\n\n  @VisibleForTesting\n  static io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext\n      validateUpstreamTlsContext(\n      io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext upstreamTlsContext,\n      Set<String> certProviderInstances)\n      throws ResourceInvalidException {\n    if (upstreamTlsContext.hasCommonTlsContext()) {\n      validateCommonTlsContext(upstreamTlsContext.getCommonTlsContext(), certProviderInstances,\n          false);\n    } else {\n      throw new ResourceInvalidException(\"common-tls-context is required in upstream-tls-context\");\n    }\n    return upstreamTlsContext;\n  }\n\n  @VisibleForTesting\n  static void validateCommonTlsContext(\n      CommonTlsContext commonTlsContext, Set<String> certProviderInstances, boolean server)\n      throws ResourceInvalidException {\n    if (commonTlsContext.hasCustomHandshaker()) {\n      throw new ResourceInvalidException(\n          \"common-tls-context with custom_handshaker is not supported\");\n    }\n    if (commonTlsContext.hasTlsParams()) {\n      throw new ResourceInvalidException(\"common-tls-context with tls_params is not supported\");\n    }\n    if (commonTlsContext.hasValidationContextSdsSecretConfig()) {\n      throw new ResourceInvalidException(\n          \"common-tls-context with validation_context_sds_secret_config is not supported\");","sourceCodeStart":424,"sourceCodeEnd":460,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/XdsClusterResource.java#L424-L460","documentation":"validateUpstreamTlsContext throws this ResourceInvalidException when an upstream_tls_context is present on a Cluster but omits its required common_tls_context sub-message. The common_tls_context carries the TLS transport-protocol config (validation context, certificates, ALPN), and gRPC's xDS implementation cannot build a TLS channel without it, so the Cluster resource is rejected.","triggerScenarios":"A Cluster resource parsed by parseNonAggregateCluster includes upstream_tls_context but leaves common_tls_context unset (hasCommonTlsContext() is false), so the else-branch throws.","commonSituations":"Control planes emitting upstream_tls_context with only extension fields; truncated or hand-trimmed config files; users migrating Envoy configs and dropping the nested block; template engines rendering empty common_tls_context that gets stripped as unset.","solutions":["Add a common_tls_context to upstream_tls_context, at minimum a validation_context with a trusted CA (e.g. combined via combined_validation_context with a CertificateValidationContext from your certificate_providers_instance).","Verify the emitted proto actually sets common_tls_context, not just sibling fields.","Check that YAML/JSON serialization is not dropping empty nested messages.","Confirm the field name/casing matches the proto (common_tls_context in JSON)."],"exampleFix":"# before\nupstream_tls_context: {}\n# after\nupstream_tls_context:\n  common_tls_context:\n    validation_context:\n      trusted_ca:\n        filename: /etc/certs/ca.pem","handlingStrategy":"validation","validationCode":"boolean hasCommonTlsContext(ClusterOuterClass.Cluster cluster) {\n  return cluster.hasUpstreamTlsContext()\n      && cluster.getUpstreamTlsContext().hasCommonTlsContext();\n}","typeGuard":"boolean hasUpstreamTls(com.envoyproxy.envoy.config.cluster.v3.Cluster c) {\n  return c.hasUpstreamTlsContext()\n      && c.getUpstreamTlsContext().hasCommonTlsContext();\n}","tryCatchPattern":"try {\n  cluster = parseCluster(raw);\n} catch (io.grpc.xds.ResourceInvalidException e) {\n  if (e.getMessage().contains(\"common-tls-context\")) {\n    log.error(\"upstream_tls_context missing common_tls_context in CDS resource\");\n  }\n  return null;\n}","preventionTips":["Always pair upstream_tls_context with a common_tls_context containing a validation_context/trusted CA.","Validate with hasCommonTlsContext() on the control plane before publishing.","Beware templating engines stripping empty nested messages like common_tls_context: {}.","Test that rendered configs round-trip through the envoy protos without dropping sub-messages."],"tags":["xds","grpc","tls","config-validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}