elastic/elasticsearch · error · SslConfigException
could not resolve ssl client authentication, unknown value [
Error message
could not resolve ssl client authentication, unknown value [{}], recognised values are [{}] What it means
SslClientAuthenticationMode.parse lowercases the input and looks it up in a fixed {none, optional, required} map. Any value not exactly matching one of those keys throws SslConfigException with the allowed list. This controls whether the server demands a client cert on inbound TLS.
Source
Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslClientAuthenticationMode.java:86
* Configure client authentication of the provided {@link SSLParameters}
*/
public abstract void configure(SSLParameters sslParameters);
private static final Map<String, SslClientAuthenticationMode> LOOKUP = Collections.unmodifiableMap(buildLookup());
static Map<String, SslClientAuthenticationMode> buildLookup() {
final Map<String, SslClientAuthenticationMode> map = new LinkedHashMap<>(3);
map.put("none", NONE);
map.put("optional", OPTIONAL);
map.put("required", REQUIRED);
return map;
}
public static SslClientAuthenticationMode parse(String value) {
final SslClientAuthenticationMode mode = LOOKUP.get(value.toLowerCase(Locale.ROOT));
if (mode == null) {
final String allowedValues = String.join(",", LOOKUP.keySet());
throw new SslConfigException(
"could not resolve ssl client authentication, unknown value [" + value + "], recognised values are [" + allowedValues + "]"
);
}
return mode;
}
}
View on GitHub (pinned to db6a809a66)
Solutions
- Set the value to one of: none, optional, required (case-insensitive, no quotes needed for YAML).
- If using a dynamic config source, trim and validate before passing to parse().
- Search the cluster settings for the affected prefix (http.ssl., transport.ssl.) and correct the typo.
Example fix
// before xpack.security.http.ssl.client_authentication: require // after xpack.security.http.ssl.client_authentication: required
Defensive patterns
Strategy: validation
Validate before calling
private static final Set<String> CLIENT_AUTH_VALUES = Set.of("none","optional","required");
String normaliseClientAuth(String raw) {
if (raw == null) return null;
String v = raw.trim().toLowerCase(Locale.ROOT);
if (!CLIENT_AUTH_VALUES.contains(v))
throw new IllegalArgumentException("ssl client_authentication must be one of " + CLIENT_AUTH_VALUES);
return v;
} Try / catch
try {
SslClientAuthenticationMode mode = SslClientAuthenticationMode.parse(raw);
} catch (SslConfigException e) {
// surface the allowed list to the operator and fail fast at config load
throw new IllegalArgumentException(e.getMessage(), e);
} Prevention
- Constrain the value at the config-source layer (enum in your templating tool).
- Add a config lint step that rejects ssl.*.client_authentication values outside the allowed set.
- Treat YAML boolean coercion as a smell — quote string settings when in doubt.
When it happens
Trigger: Calling SslClientAuthenticationMode.parse with a value other than none/optional/required (case-insensitive). Typical offenders: "require", "true", "false", "yes", "on", "mandatory", or a value with leading/trailing whitespace that the caller did not trim.
Common situations: Operator writes xpack.security.http.ssl.client_authentication: require (should be required); copies a value from another product's vocabulary; YAML boolean coercion turns the value into true/false.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- cannot configure SSL/TLS without any supported cipher suites
- cannot configure SSL/TLS without any supported protocols
- handshake timeout must be at least 1ms
- Setting prefix [{}] must be blank or end in '.'
- no protocols configured in [{}]
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/bcee33d90ab45c3c.
Report an issue: GitHub.