{"id":"01be995a1299a2fc","repo":"apache/kafka","slug":"you-cannot-set-both-bootstrap-servers-and-bootstra","errorCode":null,"errorMessage":"You cannot set both bootstrap.servers and bootstrap.controllers","messagePattern":"You cannot set both bootstrap\\.servers and bootstrap\\.controllers","errorType":"validation","errorClass":"ConfigException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java","lineNumber":551,"sourceCode":"        }\n        List<String> controllerServers = config.getList(AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG);\n        if (controllerServers == null) {\n            controllerServers = Collections.emptyList();\n        }\n\n        if (bootstrapServers.isEmpty()) {\n            if (controllerServers.isEmpty()) {\n                throw new ConfigException(\"You must set either \" +\n                    CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG + \" or \" +\n                    AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG);\n            } else {\n                return true; // Using bootstrap.controllers\n            }\n        } else {\n            if (controllerServers.isEmpty()) {\n                return false; // Using bootstrap.servers\n            } else {\n                throw new ConfigException(\"You cannot set both \" +\n                    CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG + \" and \" +\n                    AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG);\n            }\n        }\n    }\n\n    static KafkaAdminClient createInternal(AdminClientConfig config, TimeoutProcessorFactory timeoutProcessorFactory) {\n        return createInternal(config, timeoutProcessorFactory, null);\n    }\n\n    static KafkaAdminClient createInternal(\n        AdminClientConfig config,\n        TimeoutProcessorFactory timeoutProcessorFactory,\n        HostResolver hostResolver\n    ) {\n        Metrics metrics = null;\n        NetworkClient networkClient = null;\n        Time time = Time.SYSTEM;","sourceCodeStart":533,"sourceCodeEnd":569,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java#L533-L569","documentation":"Thrown by KafkaAdminClient.determineBootstrapType when both bootstrap.servers and bootstrap.controllers are non-empty in the same Admin config. The client must commit to a single bootstrap path so AdminMetadataManager and the NetworkClient know which endpoint type to target for initial metadata; specifying both is ambiguous, so construction fails fast with a ConfigException.","triggerScenarios":"Calling Admin.create with a config that contains both CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG and AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG each resolving to a non-empty list (e.g. broker endpoints in bootstrap.servers and KRaft controller endpoints in bootstrap.controllers).","commonSituations":"Migrating a cluster to KRaft and leaving the old bootstrap.servers value in place while also adding bootstrap.controllers; shared config templates that set both keys; copy-paste from examples that merge broker-only and controller-only snippets; environment overlays that append one key without clearing the other.","solutions":["Keep bootstrap.servers only if you want to bootstrap against brokers (the common case for most clients).","Keep bootstrap.controllers only if you intentionally want to bootstrap directly against KRaft controllers, and remove bootstrap.servers.","Audit config files, env vars, and Spring/Quarkus property sources to ensure only one bootstrap key is set.","If both must coist in different deployments, drive selection from a single profile/env var so only one key is non-empty at runtime."],"exampleFix":"// before\nMap<String, Object> cfg = new HashMap<>();\ncfg.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, \"broker1:9092\");\ncfg.put(AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG, \"ctrl1:9093\");\nAdmin admin = Admin.create(cfg); // throws ConfigException\n\n// after - pick ONE bootstrap source\nMap<String, Object> cfg = new HashMap<>();\ncfg.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, \"broker1:9092\");\n// bootstrap.controllers intentionally omitted\nAdmin admin = Admin.create(cfg);","handlingStrategy":"validation","validationCode":"boolean hasServers = props.containsKey(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG)\n    && !String.valueOf(props.get(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG)).isBlank();\nboolean hasControllers = props.containsKey(AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG)\n    && !String.valueOf(props.get(AdminClientConfig.BOOTSTRAP_CONTROLLERS_CONFIG)).isBlank();\nif (hasServers && hasControllers) {\n    throw new IllegalArgumentException(\"Set only ONE of bootstrap.servers or bootstrap.controllers, not both\");\n}\nAdmin admin = Admin.create(props);","typeGuard":null,"tryCatchPattern":"try {\n    Admin admin = Admin.create(props);\n} catch (ConfigException e) {\n    // 'You cannot set both bootstrap.servers and bootstrap.controllers'\n    log.error(\"Conflicting bootstrap config\", e);\n}","preventionTips":["Never merge two property Maps blindly when one may already carry bootstrap.servers; check for the key before adding bootstrap.controllers.","Pick one bootstrap strategy per deployment (servers vs controllers) and document it; reject configs that try to set both.","Unit-test your config assembly with a small assertion: exactly one bootstrap key present."],"tags":["configuration","admin-client","bootstrap","kraf","startup"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}