{"id":"177d82bddda60e36","repo":"apache/kafka","slug":"clientsaslmechanism-must-be-non-null-in-client-m","errorCode":null,"errorMessage":"`clientSaslMechanism` must be non-null in client mode if `securityProtocol` is `${securityProtocol}`","messagePattern":"`clientSaslMechanism` must be non-null in client mode if `securityProtocol` is `(.+?)`","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/network/ChannelBuilders.java","lineNumber":76,"sourceCode":"     * @param logContext the log context instance\n     *\n     * @return the configured `ChannelBuilder`\n     * @throws IllegalArgumentException if `mode` invariants described above is not maintained\n     */\n    public static ChannelBuilder clientChannelBuilder(\n            SecurityProtocol securityProtocol,\n            JaasContext.Type contextType,\n            AbstractConfig config,\n            ListenerName listenerName,\n            String clientSaslMechanism,\n            Time time,\n            LogContext logContext) {\n\n        if (securityProtocol == SecurityProtocol.SASL_PLAINTEXT || securityProtocol == SecurityProtocol.SASL_SSL) {\n            if (contextType == null)\n                throw new IllegalArgumentException(\"`contextType` must be non-null if `securityProtocol` is `\" + securityProtocol + \"`\");\n            if (clientSaslMechanism == null)\n                throw new IllegalArgumentException(\"`clientSaslMechanism` must be non-null in client mode if `securityProtocol` is `\" + securityProtocol + \"`\");\n        }\n        return create(securityProtocol, ConnectionMode.CLIENT, contextType, config, listenerName, false, clientSaslMechanism,\n            null, null, time, logContext, null);\n    }\n\n    /**\n     * @param listenerName the listenerName\n     * @param isInterBrokerListener whether or not this listener is used for inter-broker requests\n     * @param securityProtocol the securityProtocol\n     * @param config server config\n     * @param credentialCache Credential cache for SASL/SCRAM if SCRAM is enabled\n     * @param tokenCache Delegation token cache\n     * @param time the time instance\n     * @param logContext the log context instance\n     * @param apiVersionSupplier supplier for ApiVersions responses sent prior to authentication\n     *\n     * @return the configured `ChannelBuilder`\n     */","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/network/ChannelBuilders.java#L58-L94","documentation":"Thrown by `ChannelBuilders.clientChannelBuilder` when the security protocol is SASL_PLAINTEXT or SASL_SSL but `clientSaslMechanism` is null. A SASL client must name exactly which mechanism it authenticates with (PLAIN, SCRAM-SHA-256, SCRAM-SHA-512, GSSAPI, OAUTHBEARER, DELEGATION_TOKEN, etc.) because that string drives JAAS context loading and mechanism negotiation. Null would NPE during `JaasContext.loadServerContext`/client context construction, so it is rejected up front.","triggerScenarios":"Calling `ChannelBuilders.clientChannelBuilder(SASL_*, contextType, config, listenerName, null, time, logContext)`. In standard clients this surfaces when `sasl.mechanism` config is unset/blank and the bootstrap fails to resolve it to a non-null string.","commonSituations":"Forgetting to set `sasl.mechanism` in client properties (common when adding SASL_SSL to an existing PLAINTEXT client). Setting it under a listener-prefixed key that the client doesn't read. Typos like `sasl.mechanisms` (plural). Custom client wrappers that pass null instead of reading the config.","solutions":["Set `sasl.mechanism` in the client config (e.g. `props.put(\"sasl.mechanism\", \"SCRAM-SHA-512\")`).","If calling clientChannelBuilder directly, pass the resolved mechanism string explicitly.","Verify the mechanism appears in the broker's `sasl.enabled.mechanisms` for server-side compatibility."],"exampleFix":"// before\nprops.put(\"security.protocol\", \"SASL_SSL\");\n// sasl.mechanism missing\n\n// after\nprops.put(\"security.protocol\", \"SASL_SSL\");\nprops.put(\"sasl.mechanism\", \"SCRAM-SHA-512\");","handlingStrategy":"validation","validationCode":"boolean isSasl = securityProtocol == SecurityProtocol.SASL_PLAINTEXT\n                    || securityProtocol == SecurityProtocol.SASL_SSL;\nif (isSasl && (clientSaslMechanism == null || clientSaslMechanism.isEmpty())) {\n    throw new IllegalArgumentException(\n        \"clientSaslMechanism required for client-mode \" + securityProtocol);\n}\nChannelBuilders.clientChannelBuilder(\n    securityProtocol, contextType, config, listenerName, clientSaslMechanism, time, logContext);","typeGuard":null,"tryCatchPattern":"try {\n    ChannelBuilders.clientChannelBuilder(\n        securityProtocol, contextType, config, listenerName,\n        clientSaslMechanism, time, logContext);\n} catch (IllegalArgumentException e) {\n    // \"`clientSaslMechanism` must be non-null in client mode if `securityProtocol` is SASL_*\"\n    clientSaslMechanism = \"PLAIN\"; // or read from config: sasl.mechanism\n}","preventionTips":["Always set `sasl.mechanism` (clientSaslMechanism) in client config when security.protocol is SASL_*.","Validate the (securityProtocol, clientSaslMechanism) pair when parsing client configs, before builder creation.","Provide a default mechanism (e.g. PLAIN/SCRAM-SHA-256) at the config layer so SASL clients never start with null."],"tags":["network","sasl","security","client","configuration","java"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}