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

  1. Set the value to one of: none, optional, required (case-insensitive, no quotes needed for YAML).
  2. If using a dynamic config source, trim and validate before passing to parse().
  3. 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

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

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/bcee33d90ab45c3c. Report an issue: GitHub.