grpc/grpc-java · error · IllegalArgumentException
TLS version %d is not supported.
Error message
TLS version %d is not supported.
What it means
convertTlsProtocolVersion maps S2A handshaker protobuf TLSVersion enum values to Java TLS protocol-name strings. The default branch throws this IllegalArgumentException when the proto enum carries a value outside the supported set (TLS 1.0/1.1/1.2), typically because the S2A handshaker server sent an enum value this client build does not know (e.g. TLS 1.3 in an older client).
Source
Thrown at s2a/src/main/java/io/grpc/s2a/internal/handshaker/ProtoUtil.java:46
*
* @param tlsVersion the {@link TLSVersion} object to be converted.
* @return a {@link String} representation of the TLS version.
* @throws IllegalArgumentException if the {@code tlsVersion} is not one of
* the supported TLS versions.
*/
@VisibleForTesting
static String convertTlsProtocolVersion(TLSVersion tlsVersion) {
switch (tlsVersion) {
case TLS_VERSION_1_3:
return "TLSv1.3";
case TLS_VERSION_1_2:
return "TLSv1.2";
case TLS_VERSION_1_1:
return "TLSv1.1";
case TLS_VERSION_1_0:
return "TLSv1";
default:
throw new IllegalArgumentException(
String.format("TLS version %d is not supported.", tlsVersion.getNumber()));
}
}
/**
* Builds a set of strings representing all {@link TLSVersion}s between {@code minTlsVersion} and
* {@code maxTlsVersion}.
*/
static ImmutableSet<String> buildTlsProtocolVersionSet(
TLSVersion minTlsVersion, TLSVersion maxTlsVersion) {
ImmutableSet.Builder<String> tlsVersions = ImmutableSet.<String>builder();
for (TLSVersion tlsVersion : TLSVersion.values()) {
int versionNumber;
try {
versionNumber = tlsVersion.getNumber();
} catch (IllegalArgumentException e) {
continue;
}View on GitHub (pinned to 64daddc1f3)
Solutions
- Upgrade the gRPC s2a client/handshaker library to a version whose proto and mapping include the TLS version S2A returns.
- Constrain the S2A policy's min/max TLS versions to 1.0–1.2 (ideally just TLS 1.2) until versions are aligned.
- Check the handshaker proto: ensure both sides are generated from the same tls.proto version so enum numbers match.
- Log tlsVersion.getNumber() on failure to identify the offending enum value and confirm the diagnosis.
Example fix
// before (older client) min_tls_version: TLS_VERSION_1_3 // after min_tls_version: TLS_VERSION_1_2 // or upgrade client library to support TLS 1.3
Defensive patterns
Strategy: validation
Validate before calling
static void checkSupportedTlsVersion(TLSVersion v) {
switch (v) {
case TLS_VERSION_1_0:
case TLS_VERSION_1_1:
case TLS_VERSION_1_2:
return;
default:
throw new IllegalArgumentException("TLS version " + v.getNumber() + " unsupported by client");
}
} Prevention
- Pin min/max TLS versions to values the client library maps (ideally 1.2 only).
- Keep s2a client and handshaker proto versions in lockstep with the S2A service.
- Prefer TLS 1.2/1.3 policy consistently; never send TLS_VERSION_UNSPECIFIED.
- Log the raw enum number on unsupported values to detect version skew fast.
When it happens
Trigger: Calling buildTlsProtocolVersionSet (invoked during S2A channel setup) with min/max TLS versions where a version is TLS_VERSION_UNSPECIFIED, out-of-range, or a newer enum constant (e.g. TLS_VERSION_1_3) unrecognized by the mapped switch in this client version.
Common situations: S2A server upgraded to support TLS 1.3 while the gRPC s2a client library predates that enum value; misconfigured S2A policy returning TLS_VERSION_UNSPECIFIED; version skew between handshaker proto files.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Unsupported provider: ${provider}
- Signature Algorithm %d is not supported.
- Error occurred in response from S2A, error code: %d, error m
- No valid response received from S2A.
- decrypt is not supported.
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/d35668706933c87e.
Report an issue: GitHub.