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
- Pick one mode: keep bootstrap.servers for normal Admin usage, or bootstrap.controllers for direct controller access, and remove the other.
- When layering configs, explicitly null/remove the key you are not using.
- 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
- Pick one bootstrap mode per environment and remove the other key.
- When layering configs, explicitly null the key you are not using.
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
- You must set either bootstrap.servers or…
- The specified value of default.api.timeout.ms must be no…
- Cannot request fenced brokers from controller endpoint
- Expected response from CONTROLLER endpoint, but got…
- Failed to create new KafkaAdminClient
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)