grpc/grpc-java · error · ResourceInvalidException
common-tls-context with custom_handshaker is not supported
Error message
common-tls-context with custom_handshaker is not supported
What it means
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.
Source
Thrown at xds/src/main/java/io/grpc/xds/XdsClusterResource.java:452
validateUpstreamTlsContext(
io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext upstreamTlsContext,
Set<String> certProviderInstances)
throws ResourceInvalidException {
if (upstreamTlsContext.hasCommonTlsContext()) {
validateCommonTlsContext(upstreamTlsContext.getCommonTlsContext(), certProviderInstances,
false);
} else {
throw new ResourceInvalidException("common-tls-context is required in upstream-tls-context");
}
return upstreamTlsContext;
}
@VisibleForTesting
static void validateCommonTlsContext(
CommonTlsContext commonTlsContext, Set<String> certProviderInstances, boolean server)
throws ResourceInvalidException {
if (commonTlsContext.hasCustomHandshaker()) {
throw new ResourceInvalidException(
"common-tls-context with custom_handshaker is not supported");
}
if (commonTlsContext.hasTlsParams()) {
throw new ResourceInvalidException("common-tls-context with tls_params is not supported");
}
if (commonTlsContext.hasValidationContextSdsSecretConfig()) {
throw new ResourceInvalidException(
"common-tls-context with validation_context_sds_secret_config is not supported");
}
String certInstanceName = getIdentityCertInstanceName(commonTlsContext);
if (certInstanceName == null) {
if (server) {
throw new ResourceInvalidException(
"tls_certificate_provider_instance is required in downstream-tls-context");
}
if (commonTlsContext.getTlsCertificatesCount() > 0) {
throw new ResourceInvalidException(
"tls_certificate_provider_instance is unset");View on GitHub (pinned to 64daddc1f3)
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).
Example fix
// before (cluster common_tls_context)
"common_tls_context": { "custom_handshaker": { "name": "envoy.tls.handshaker.custom" } }
// after
"common_tls_context": { "tls_params": null, "validation_context": { "trusted_ca": { ... } } } Defensive patterns
Strategy: validation
Validate before calling
// Java: inspect proto before submitting resource
if (commonTlsContext.hasCustomHandshaker()) {
throw new IllegalArgumentException("custom_handshaker unsupported by grpc-xds");
} Try / catch
try {
clusterAccepted = xdsClient.watchClusterResource(name, watcher);
} catch (ResourceInvalidException e) {
logger.warning("Cluster rejected: " + e.getMessage()); // surface control-plane config error
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- common-tls-context is required in upstream-tls-context
- common-tls-context with tls_params is not supported
- common-tls-context with validation_context_sds_secret_config
- tls_certificate_provider_instance is required in downstream-
- tls_certificate_provider_instance is unset
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/69e6b0df8d7b7fdf.
Report an issue: GitHub.