apache/kafka · error · ConfigException

When the security.protocol configuration enables SASL…

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 the security.protocol is SASL_PLAINTEXT or SASL_SSL but sasl.mechanism is null or empty. The post-validation runs after the config is parsed, ensuring a SASL-enabled protocol always has a concrete mechanism to negotiate. This is a fail-fast guard against an incomplete SASL setup.

Solutions

  1. Set sasl.mechanism to a supported value, e.g. 'SCRAM-SHA-512', 'PLAIN', 'GSSAPI', or 'OAUTHBEARER'.
  2. Ensure the matching jaas config and login handler are configured for that mechanism.
  3. If you did not intend SASL, set security.protocol back to PLAINTEXT or SSL.
  4. Verify the override chain (global vs producer/consumer/admin) actually sets the mechanism.

Example fix

# before
security.protocol=SASL_SSL
# sasl.mechanism missing
# after
security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-512
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
  username="user" password="secret";
Defensive patterns

Strategy: validation

Validate before calling

SecurityProtocol sp = SecurityProtocol.forName(config.getString(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG));
String mech = config.getString(SaslConfigs.SASL_MECHANISM);
if ((sp == SecurityProtocol.SASL_PLAINTEXT || sp == SecurityProtocol.SASL_SSL) && (mech == null || mech.isEmpty()))
  throw new ConfigException(SaslConfigs.SASL_MECHANISM, null, "SASL protocol requires a non-empty mechanism");

Try / catch

try { CommonClientConfigs.postValidateSaslMechanismConfig(config); } catch (ConfigException e) { if (e.message.contains('mechanism must be non-null')) { /* set sasl.mechanism */ } else throw e; }

Prevention

When it happens

Trigger: At line 322, after reading security.protocol and sasl.mechanism, if the protocol is one of the two SASL variants and clientSaslMechanism is null/empty, throw ConfigException naming SASL_MECHANISM. Triggered by setting security.protocol=SASL_SSL/SASL_PLAINTEXT without sasl.mechanism.

Common situations: Switching from PLAINTEXT/SSL to SASL_SSL and forgetting sasl.mechanism; jaas config present but mechanism missing; templated config that leaves mechanism blank; mechanism supplied only in a client-specific override that did not apply.

Related errors


AI-assisted analysis of apache/kafka@996fb4585a (2026-08-11). Data as JSON: /api/errors/1dd0b72df100a5c6. Report an issue: GitHub.

Appendix: 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 996fb4585a)