{"record":{"id":"ceb6c357a2a8c86b","repo":"apache/kafka","slug":"topicidfutures-and-namefutures-cannot-both-be-null-ceb6c3","errorCode":null,"errorMessage":"topicIdFutures and nameFutures cannot both be null.","messagePattern":"topicIdFutures and nameFutures cannot both be null\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/admin/DescribeTopicsResult.java","lineNumber":43,"sourceCode":"import java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.ExecutionException;\n\n/**\n * The result of the {@link KafkaAdminClient#describeTopics(Collection)} call.\n */\n@InterfaceAudience.Public\npublic class DescribeTopicsResult {\n    private final Map<Uuid, KafkaFuture<TopicDescription>> topicIdFutures;\n    private final Map<String, KafkaFuture<TopicDescription>> nameFutures;\n\n    // VisibleForTesting\n    protected DescribeTopicsResult(Map<Uuid, KafkaFuture<TopicDescription>> topicIdFutures, Map<String, KafkaFuture<TopicDescription>> nameFutures) {\n        if (topicIdFutures != null && nameFutures != null)\n            throw new IllegalArgumentException(\"topicIdFutures and nameFutures cannot both be specified.\");\n        if (topicIdFutures == null && nameFutures == null)\n            throw new IllegalArgumentException(\"topicIdFutures and nameFutures cannot both be null.\");\n        this.topicIdFutures = topicIdFutures;\n        this.nameFutures = nameFutures;\n    }\n\n    static DescribeTopicsResult ofTopicIds(Map<Uuid, KafkaFuture<TopicDescription>> topicIdFutures) {\n        return new DescribeTopicsResult(topicIdFutures, null);\n    }\n\n    static DescribeTopicsResult ofTopicNames(Map<String, KafkaFuture<TopicDescription>> nameFutures) {\n        return new DescribeTopicsResult(null, nameFutures);\n    }\n\n    /**\n     * Use when {@link Admin#describeTopics(TopicCollection, DescribeTopicsOptions)} used a TopicIdCollection\n     *\n     * @return a map from topic IDs to futures which can be used to check the status of\n     *         individual topics if the request used topic IDs, otherwise return null.\n     */","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/apache/kafka/blob/996fb4585aa1bcc8980b0e1b8d6b168b986cd979/clients/src/main/java/org/apache/kafka/clients/admin/DescribeTopicsResult.java#L25-L61","documentation":"Thrown by the DescribeTopicsResult protected constructor when both topicIdFutures and nameFutures are null. The result must contain exactly one future map; providing neither makes it impossible to retrieve any topic descriptions.","triggerScenarios":"Directly constructing DescribeTopicsResult (or subclass) with null for both future maps.","commonSituations":"A subclass or test path that conditionally selects a map but resolves to none, or a copy-paste error passing null for both arguments.","solutions":["Use ofTopicIds / ofTopicNames to guarantee exactly one map is provided.","In subclasses, assert that exactly one map is non-null before delegating to super.","Review construction call sites to ensure the selection logic always yields one map."],"exampleFix":"// before\nnew DescribeTopicsResult(null, null);\n\n// after\nDescribeTopicsResult.ofTopicNames(nameMap);","handlingStrategy":"validation","validationCode":"if ((idMap == null) == (nameMap == null)) {\n    throw new IllegalArgumentException(\"Exactly one of topicIdFutures/nameFutures required\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the static factories to guarantee exactly one map is set.","In subclasses, assert the either/or invariant.","Audit construction paths so selection logic always yields one map."],"tags":["validation","admin","invariant"],"backgroundTag":null,"analyzedSha":"996fb4585aa1bcc8980b0e1b8d6b168b986cd979","analyzedAt":"2026-08-11T22:03:28.655Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}