{"record":{"id":"69e6b0df8d7b7fdf","repo":"grpc/grpc-java","slug":"common-tls-context-with-custom-handshaker-is-not-s","errorCode":null,"errorMessage":"common-tls-context with custom_handshaker is not supported","messagePattern":"common-tls-context with custom_handshaker is not supported","errorType":"validation","errorClass":"ResourceInvalidException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/XdsClusterResource.java","lineNumber":452,"sourceCode":"      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\");\n    }\n    String certInstanceName = getIdentityCertInstanceName(commonTlsContext);\n    if (certInstanceName == null) {\n      if (server) {\n        throw new ResourceInvalidException(\n            \"tls_certificate_provider_instance is required in downstream-tls-context\");\n      }\n      if (commonTlsContext.getTlsCertificatesCount() > 0) {\n        throw new ResourceInvalidException(\n            \"tls_certificate_provider_instance is unset\");","sourceCodeStart":434,"sourceCodeEnd":470,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/XdsClusterResource.java#L434-L470","documentation":"gRPC's xDS cluster resource parsing rejects a CommonTlsContext that carries a custom_handshaker because the Java xDS client only implements the standard Envoy TLS handshake path. Custom handshake extensions cannot be mapped to gRPC's transport, so the whole cluster resource is marked invalid. This check runs inside validateCommonTlsContext during UpstreamTlsContext (and downstream) validation.","triggerScenarios":"An xDS CDS/LDS resource (cluster with upstream_tls_context or listener with downstream_tls_context) whose common_tls_context contains a non-empty custom_handshaker field. Thrown as ResourceInvalidException from validateCommonTlsContext when validateUpstreamTlsContext processes the cluster resource.","commonSituations":"Control planes (e.g. Envoy-oriented tooling or ISVs) that generate config with custom TLS handshake extensions; reuse of Envoy-optimized configurations that gRPC xDS never supported; copy-paste of production Envoy bootstrap clusters into a gRPC application.","solutions":["Remove the custom_handshaker field from common_tls_context in the xDS resource so gRPC uses the standard TLS handshake.","If a custom handshake is required, use Envoy as the data plane instead of gRPC's xDS client, or terminate TLS at a proxy sidecar.","Ensure the control plane filters/omits unsupported fields when generating resources for gRPC clients (per gRFC A-53 style unsupported-field handling)."],"exampleFix":"// before (cluster common_tls_context)\n\"common_tls_context\": { \"custom_handshaker\": { \"name\": \"envoy.tls.handshaker.custom\" } }\n// after\n\"common_tls_context\": { \"tls_params\": null, \"validation_context\": { \"trusted_ca\": { ... } } }","handlingStrategy":"validation","validationCode":"// Java: inspect proto before submitting resource\nif (commonTlsContext.hasCustomHandshaker()) {\n  throw new IllegalArgumentException(\"custom_handshaker unsupported by grpc-xds\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  clusterAccepted = xdsClient.watchClusterResource(name, watcher);\n} catch (ResourceInvalidException e) {\n  logger.warning(\"Cluster rejected: \" + e.getMessage()); // surface control-plane config error\n}","preventionTips":["Keep Envoy-only TLS extensions out of resources served to gRPC clients.","Filter generated resources against gRPC's supported-field list before pushing them via CDS/LDS."],"tags":["grpc","xds","tls","unsupported-field"],"backgroundTag":"unsupported-config-value","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"}