{"id":"a11561801d437c47","repo":"apache/kafka","slug":"contexttype-must-be-non-null-if-securityprotoco","errorCode":null,"errorMessage":"`contextType` must be non-null if `securityProtocol` is `${securityProtocol}`","messagePattern":"`contextType` must be non-null if `securityProtocol` is `(.+?)`","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/network/ChannelBuilders.java","lineNumber":74,"sourceCode":"     * @param clientSaslMechanism SASL mechanism if mode is CLIENT, ignored otherwise\n     * @param time the time instance\n     * @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     *","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/network/ChannelBuilders.java#L56-L92","documentation":"Thrown by `ChannelBuilders.clientChannelBuilder` when the security protocol is SASL_PLAINTEXT or SASL_SSL but the `contextType` argument (a `JaasContext.Type`) is null. SASL channels need a JAAS login context to authenticate, and in client mode the caller must say whether to load the CLIENT jaas config or the SERVER (inter-broker) one. Null contextType would cause an NPE deeper in JaasContext loading, so Kafka rejects it at the entry point.","triggerScenarios":"Calling `ChannelBuilders.clientChannelBuilder(SASL_PLAINTEXT|SASL_SSL, null, config, listenerName, clientSaslMechanism, time, logContext)` — i.e. contextType is null while the protocol is SASL_*. Hit internally by Kafka client bootstrap (Admin/Producer/Consumer) when assembling the channel builder from client configs.","commonSituations":"A custom client wrapper that constructs a SASL channel but forgets to pass `JaasContext.Type.CLIENT`. Migrating a PLAINTEXT client to SASL without updating the bootstrap code. Framework integration (Spring/Quarkus) that injects null for the JAAS context type. Inter-broker or tooling code that only conditionally sets contextType.","solutions":["Pass `JaasContext.Type.CLIENT` for normal clients (or `JausContext.Type.SERVER` for inter-broker client connections).","Prefer the high-level `KafkaProducer`/`KafkaConsumer`/`AdminClient` APIs which derive contextType from configs rather than calling clientChannelBuilder directly.","If writing a custom ChannelBuilder entry point, guard contextType before calling clientChannelBuilder."],"exampleFix":"// before\nChannelBuilders.clientChannelBuilder(\n    SecurityProtocol.SASL_SSL, null, config, null, \"SCRAM-SHA-512\", time, logContext);\n\n// after\nChannelBuilders.clientChannelBuilder(\n    SecurityProtocol.SASL_SSL, JaasContext.Type.CLIENT, config, null, \"SCRAM-SHA-512\", time, logContext);","handlingStrategy":"validation","validationCode":"boolean isSasl = securityProtocol == SecurityProtocol.SASL_PLAINTEXT\n                    || securityProtocol == SecurityProtocol.SASL_SSL;\nif (isSasl && contextType == null) {\n    throw new IllegalArgumentException(\n        \"contextType required for securityProtocol \" + 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    // \"`contextType` must be non-null if `securityProtocol` is SASL_*\"\n    if (securityProtocol == SecurityProtocol.SASL_PLAINTEXT\n            || securityProtocol == SecurityProtocol.SASL_SSL) {\n        contextType = JaasContext.Type.CLIENT;\n    }\n}","preventionTips":["Pair every SASL_* securityProtocol with a non-null JaasContext.Type when calling clientChannelBuilder.","Derive contextType from the security protocol in one helper so SASL never reaches the builder without a type.","Treat null contextType as valid only for PLAINTEXT/SSL; assert the SASL=>non-null invariant in config validation."],"tags":["network","sasl","security","jaas","client","configuration","java"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}