apache/kafka · error · ConfigException

You must set either bootstrap.servers or…

Error message

You must set either bootstrap.servers or bootstrap.controllers

What it means

Thrown by KafkaAdminClient.determineBootstrapType (a ConfigException) when neither bootstrap.servers nor bootstrap.controllers is configured. The Admin client needs at least one entry point to contact the cluster.

Solutions

  1. Set AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG to a comma-separated host:port list (most common).
  2. Or set AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG when talking directly to KRaft controllers.
  3. Log the resolved config map in dev to catch empty/typo'd keys early.

Example fix

// before
Map<String, Object> cfg = new HashMap<>();
// bootstrap.servers missing
Admin.create(cfg);

// after
Map<String, Object> cfg = new HashMap<>();
cfg.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, "broker1:9092,broker2:9092");
Admin.create(cfg);
Defensive patterns

Strategy: validation

Validate before calling

String servers = (String) props.get(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG);
String controllers = (String) props.get(AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG);
if ((servers == null || servers.isEmpty()) && (controllers == null || controllers.isEmpty())) {
    throw new IllegalStateException("Configure bootstrap.servers or bootstrap.controllers");
}

Try / catch

try {
    Admin.create(props);
} catch (ConfigException e) {
    if (e.getMessage().contains("bootstrap")) { /* fix config, retry */ }
}

Prevention

When it happens

Trigger: Building an Admin with a Properties/Map that omits both CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG and AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG. Setting the key to an empty string. Reading config from a file where the property was commented out.

Common situations: Copy-pasting an Admin config block and dropping the bootstrap line; property-name typo (e.g. bootstrap.server without the s); env-var substitution that resolved to empty; migrating from bootstrap.servers to bootstrap.controllers but forgetting to actually set the new key.

Related errors


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

Appendix: source

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

     * Validates that exactly one of bootstrap.servers or bootstrap.controllers is configured.
     *
     * @param config The admin client configuration
     * @return true if using bootstrap.controllers, false if using bootstrap.servers
     * @throws ConfigException if both or neither bootstrap configurations are set
     */
    static boolean determineBootstrapType(AdminClientConfig config) {
        List<String> bootstrapServers = config.getList(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG);
        if (bootstrapServers == null) {
            bootstrapServers = Collections.emptyList();
        }
        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);

View on GitHub (pinned to 996fb4585a)