apache/kafka · error · ConfigException

You cannot set both bootstrap.servers and…

Error message

You cannot set both bootstrap.servers and bootstrap.controllers

What it means

Thrown by KafkaAdminClient.determineBootstrapType (a ConfigException) when both bootstrap.servers and bootstrap.controllers are set. The two are mutually exclusive: one targets brokers, the other targets KRaft controllers, and the client cannot decide which to use.

Solutions

  1. Pick one mode: keep bootstrap.servers for normal Admin usage, or bootstrap.controllers for direct controller access, and remove the other.
  2. When layering configs, explicitly null/remove the key you are not using.
  3. Validate the config map programmatically: assert exactly one of the two keys is non-empty.

Example fix

// before
props.put("bootstrap.servers", "broker:9092");
props.put("bootstrap.controllers", "ctrl:9093");

// after (broker mode)
props.put("bootstrap.servers", "broker:9092");
props.remove("bootstrap.controllers");
Defensive patterns

Strategy: validation

Validate before calling

boolean hasServers = props.containsKey(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG)
    && !((String) props.get(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG)).isEmpty();
boolean hasControllers = props.containsKey(AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG)
    && !((String) props.get(AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG)).isEmpty();
if (hasServers && hasControllers) {
    throw new IllegalStateException("Set exactly one of bootstrap.servers / bootstrap.controllers");
}

Try / catch

try {
    Admin.create(props);
} catch (ConfigException e) {
    if (e.getMessage().contains("cannot set both")) {
        props.remove(AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG);
        Admin.create(props);
    }
}

Prevention

When it happens

Trigger: A config map containing both CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG and AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG with non-empty values. Merging a base config (with bootstrap.servers) with an overlay (with bootstrap.controllers) without clearing the other.

Common situations: Switching a deployment from broker bootstrap to controller bootstrap but leaving the old property in the config file; shared config template that sets both 'just in case'; environment-specific overrides layered on top of defaults.

Related errors


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

Appendix: source

Thrown at clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java:554

        }
        List<String> controllerServers = config.getList(AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG);
        if (controllerServers == null) {
            controllerServers = Collections.emptyList();
        }

        if (bootstrapServers.isEmpty()) {
            if (controllerServers.isEmpty()) {
                throw new ConfigException("You must set either " +
                    CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG + " or " +
                    AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG);
            } else {
                return true; // Using bootstrap.controllers
            }
        } else {
            if (controllerServers.isEmpty()) {
                return false; // Using bootstrap.servers
            } else {
                throw new ConfigException("You cannot set both " +
                    CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG + " and " +
                    AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG);
            }
        }
    }

    static KafkaAdminClient createInternal(AdminClientConfig config, TimeoutProcessorFactory timeoutProcessorFactory) {
        return createInternal(config, timeoutProcessorFactory, null);
    }

    static KafkaAdminClient createInternal(
        AdminClientConfig config,
        TimeoutProcessorFactory timeoutProcessorFactory,
        HostResolver hostResolver
    ) {
        Metrics metrics = null;
        NetworkClient networkClient = null;
        Time time = Time.SYSTEM;

View on GitHub (pinned to 996fb4585a)