apache/kafka · error · ConfigException
When the security.protocol configuration enables SASL, mecha
Error message
When the security.protocol configuration enables SASL, mechanism must be non-null and non-empty string.
What it means
ConfigException thrown by CommonClientConfigs.postValidateSaslMechanismConfig when security.protocol is SASL_PLAINTEXT or SASL_SSL but sasl.mechanism is null or empty. The validation runs after config parsing and guarantees a SASL client cannot be constructed without a concrete mechanism to negotiate.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/CommonClientConfigs.java:322
RETRY_BACKOFF_MAX_MS_CONFIG, retryBackoffMaxMs, retryBackoffMaxMs);
}
long connectionSetupTimeoutMs = config.getLong(SOCKET_CONNECTION_SETUP_TIMEOUT_MS_CONFIG);
long connectionSetupTimeoutMaxMs = config.getLong(SOCKET_CONNECTION_SETUP_TIMEOUT_MAX_MS_CONFIG);
if (connectionSetupTimeoutMs > connectionSetupTimeoutMaxMs) {
log.warn("Configuration '{}' with value '{}' is greater than configuration '{}' with value '{}'. " +
"A static connection setup timeout with value '{}' will be applied.",
SOCKET_CONNECTION_SETUP_TIMEOUT_MS_CONFIG, connectionSetupTimeoutMs,
SOCKET_CONNECTION_SETUP_TIMEOUT_MAX_MS_CONFIG, connectionSetupTimeoutMaxMs, connectionSetupTimeoutMaxMs);
}
}
public static void postValidateSaslMechanismConfig(AbstractConfig config) {
SecurityProtocol securityProtocol = SecurityProtocol.forName(config.getString(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG));
String clientSaslMechanism = config.getString(SaslConfigs.SASL_MECHANISM);
if (securityProtocol == SecurityProtocol.SASL_PLAINTEXT || securityProtocol == SecurityProtocol.SASL_SSL) {
if (clientSaslMechanism == null || clientSaslMechanism.isEmpty()) {
throw new ConfigException(SaslConfigs.SASL_MECHANISM, null, "When the " + CommonClientConfigs.SECURITY_PROTOCOL_CONFIG +
" configuration enables SASL, mechanism must be non-null and non-empty string.");
}
}
}
public static List<MetricsReporter> metricsReporters(AbstractConfig config) {
return metricsReporters(Collections.emptyMap(), config);
}
public static List<MetricsReporter> metricsReporters(String clientId, AbstractConfig config) {
return metricsReporters(Collections.singletonMap(CommonClientConfigs.CLIENT_ID_CONFIG, clientId), config);
}
public static List<MetricsReporter> metricsReporters(Map<String, Object> clientIdOverride, AbstractConfig config) {
return config.getConfiguredInstances(CommonClientConfigs.METRIC_REPORTER_CLASSES_CONFIG,
MetricsReporter.class, clientIdOverride);
}
View on GitHub (pinned to c31c9215e1)
Solutions
- Set sasl.mechanism to a supported value: PLAIN, SCRAM-SHA-256, SCRAM-SHA-512, GSSAPI, OAUTHBEARER, etc.
- Confirm the property key is exactly 'sasl.mechanism' (singular) and not blank.
- If using a jaas.config, ensure the login module matches the chosen mechanism.
Example fix
// before
props.put("security.protocol", "SASL_SSL");
// sasl.mechanism missing -> ConfigException
// after
props.put("security.protocol", "SASL_SSL");
props.put("sasl.mechanism", "SCRAM-SHA-512"); Defensive patterns
Strategy: validation
Validate before calling
// If security.protocol is SASL_PLAINTEXT or SASL_SSL, the sasl.mechanism
// must be set to a non-empty string. Validate the pair together:
import org.apache.kafka.common.security.auth.SecurityProtocol;
static void validateSasl(Map<String, Object> props) {
String sp = (String) props.getOrDefault("security.protocol", "PLAINTEXT");
SecurityProtocol proto = SecurityProtocol.forName(sp);
if (proto == SecurityProtocol.SASL_PLAINTEXT || proto == SecurityProtocol.SASL_SSL) {
String mech = (String) props.get("sasl.mechanism");
if (mech == null || mech.isBlank())
throw new IllegalArgumentException(
"sasl.mechanism must be set when security.protocol=" + sp);
}
} Type guard
static boolean needsSaslMechanism(String securityProtocol) {
SecurityProtocol p = SecurityProtocol.forName(securityProtocol);
return p == SecurityProtocol.SASL_PLAINTEXT || p == SecurityProtocol.SASL_SSL;
}
// if (needsSaslMechanism(sp) && (mech == null || mech.isBlank())) fail(); Try / catch
try {
consumer = new KafkaConsumer<>(props);
} catch (ConfigException e) {
if (e.getMessage().contains("mechanism must be non-null and non-empty")) {
// Pair the security.protocol with the matching default mechanism,
// or fail the deploy and ask the operator to set sasl.mechanism.
throw new ConfigurationException("Set sasl.mechanism (e.g. SCRAM-SHA-512, PLAIN, GSSAPI)", e);
}
throw e;
} Prevention
- Treat security.protocol and sasl.mechanism as a paired setting — never set one without the other in the same config commit.
- Use well-known mechanism names verbatim (PLAIN, SCRAM-SHA-256, SCRAM-SHA-512, GSSAPI, OAUTHBEARER); a typo is the same as missing.
- Centralise security config so it cannot drift between producer and consumer instances of the same app.
- Add a config self-test in CI that constructs (and immediately closes) a client with the production security settings.
When it happens
Trigger: Setting 'security.protocol=SASL_SSL' (or SASL_PLAINTEXT) without setting 'sasl.mechanism', or setting it to an empty string. Triggered by any client constructor that runs postConfigureSasl on its AbstractConfig.
Common situations: Switching a client from PLAINTEXT to SASL_SSL for the first time and forgetting the mechanism; loading mechanism from a property whose key is misspelled (e.g. 'sasl.mechanisms'); or env var unset.
Related errors
- `mode` must be non-null if `securityProtocol` is `${security
- Invalid url in bootstrap.servers: {url}
- Invalid url in bootstrap.servers: {url}
- Invalid port in bootstrap.servers: {url}
- Illegal MetadataRecoveryStrategy: null
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/1dd0b72df100a5c6.json.
Report an issue: GitHub.