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

  1. Set sasl.mechanism to a supported value: PLAIN, SCRAM-SHA-256, SCRAM-SHA-512, GSSAPI, OAUTHBEARER, etc.
  2. Confirm the property key is exactly 'sasl.mechanism' (singular) and not blank.
  3. 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

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


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/1dd0b72df100a5c6.json. Report an issue: GitHub.