apache/kafka · error · IllegalArgumentException

`contextType` must be non-null if `securityProtocol` is `${s

Error message

`contextType` must be non-null if `securityProtocol` is `${securityProtocol}`

What it means

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.

Source

Thrown at clients/src/main/java/org/apache/kafka/common/network/ChannelBuilders.java:74

     * @param clientSaslMechanism SASL mechanism if mode is CLIENT, ignored otherwise
     * @param time the time instance
     * @param logContext the log context instance
     *
     * @return the configured `ChannelBuilder`
     * @throws IllegalArgumentException if `mode` invariants described above is not maintained
     */
    public static ChannelBuilder clientChannelBuilder(
            SecurityProtocol securityProtocol,
            JaasContext.Type contextType,
            AbstractConfig config,
            ListenerName listenerName,
            String clientSaslMechanism,
            Time time,
            LogContext logContext) {

        if (securityProtocol == SecurityProtocol.SASL_PLAINTEXT || securityProtocol == SecurityProtocol.SASL_SSL) {
            if (contextType == null)
                throw new IllegalArgumentException("`contextType` must be non-null if `securityProtocol` is `" + securityProtocol + "`");
            if (clientSaslMechanism == null)
                throw new IllegalArgumentException("`clientSaslMechanism` must be non-null in client mode if `securityProtocol` is `" + securityProtocol + "`");
        }
        return create(securityProtocol, ConnectionMode.CLIENT, contextType, config, listenerName, false, clientSaslMechanism,
            null, null, time, logContext, null);
    }

    /**
     * @param listenerName the listenerName
     * @param isInterBrokerListener whether or not this listener is used for inter-broker requests
     * @param securityProtocol the securityProtocol
     * @param config server config
     * @param credentialCache Credential cache for SASL/SCRAM if SCRAM is enabled
     * @param tokenCache Delegation token cache
     * @param time the time instance
     * @param logContext the log context instance
     * @param apiVersionSupplier supplier for ApiVersions responses sent prior to authentication
     *

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Pass `JaasContext.Type.CLIENT` for normal clients (or `JausContext.Type.SERVER` for inter-broker client connections).
  2. Prefer the high-level `KafkaProducer`/`KafkaConsumer`/`AdminClient` APIs which derive contextType from configs rather than calling clientChannelBuilder directly.
  3. If writing a custom ChannelBuilder entry point, guard contextType before calling clientChannelBuilder.

Example fix

// before
ChannelBuilders.clientChannelBuilder(
    SecurityProtocol.SASL_SSL, null, config, null, "SCRAM-SHA-512", time, logContext);

// after
ChannelBuilders.clientChannelBuilder(
    SecurityProtocol.SASL_SSL, JaasContext.Type.CLIENT, config, null, "SCRAM-SHA-512", time, logContext);
Defensive patterns

Strategy: validation

Validate before calling

boolean isSasl = securityProtocol == SecurityProtocol.SASL_PLAINTEXT
                    || securityProtocol == SecurityProtocol.SASL_SSL;
if (isSasl && contextType == null) {
    throw new IllegalArgumentException(
        "contextType required for securityProtocol " + securityProtocol);
}
ChannelBuilders.clientChannelBuilder(
    securityProtocol, contextType, config, listenerName, clientSaslMechanism, time, logContext);

Try / catch

try {
    ChannelBuilders.clientChannelBuilder(
        securityProtocol, contextType, config, listenerName,
        clientSaslMechanism, time, logContext);
} catch (IllegalArgumentException e) {
    // "`contextType` must be non-null if `securityProtocol` is SASL_*"
    if (securityProtocol == SecurityProtocol.SASL_PLAINTEXT
            || securityProtocol == SecurityProtocol.SASL_SSL) {
        contextType = JaasContext.Type.CLIENT;
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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