{"record":{"id":"1366c25090e2f210","repo":"apache/kafka","slug":"topicidfutures-and-namefutures-cannot-both-be-null","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/DeleteTopicsResult.java","lineNumber":40,"sourceCode":"import org.apache.kafka.common.Uuid;\nimport org.apache.kafka.common.annotation.InterfaceAudience;\n\nimport java.util.Collection;\nimport java.util.Map;\n\n/**\n * The result of the {@link Admin#deleteTopics(Collection)} call.\n */\n@InterfaceAudience.Public\npublic class DeleteTopicsResult {\n    private final Map<Uuid, KafkaFuture<Void>> topicIdFutures;\n    private final Map<String, KafkaFuture<Void>> nameFutures;\n\n    protected DeleteTopicsResult(Map<Uuid, KafkaFuture<Void>> topicIdFutures, Map<String, KafkaFuture<Void>> 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 DeleteTopicsResult ofTopicIds(Map<Uuid, KafkaFuture<Void>> topicIdFutures) {\n        return new DeleteTopicsResult(topicIdFutures, null);\n    }\n\n    static DeleteTopicsResult ofTopicNames(Map<String, KafkaFuture<Void>> nameFutures) {\n        return new DeleteTopicsResult(null, nameFutures);\n    }\n\n    /**\n     * Use when {@link Admin#deleteTopics(TopicCollection, DeleteTopicsOptions)} used a TopicIdCollection\n     * @return a map from topic IDs to futures which can be used to check the status of\n     * individual deletions if the deleteTopics request used topic IDs. Otherwise return null.\n     */\n    public Map<Uuid, KafkaFuture<Void>> topicIdValues() {","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/apache/kafka/blob/996fb4585aa1bcc8980b0e1b8d6b168b986cd979/clients/src/main/java/org/apache/kafka/clients/admin/DeleteTopicsResult.java#L22-L58","documentation":"Thrown by the DeleteTopicsResult protected constructor when both topicIdFutures and nameFutures are null. The result must carry exactly one future map; supplying neither leaves the object in an unusable state with no way to look up results.","triggerScenarios":"Directly instantiating DeleteTopicsResult (or subclass) with null for both the topicIdFutures and nameFutures arguments.","commonSituations":"Subclass or test code mistakenly passes null/null, or a code path that conditionally builds both maps but ends up selecting neither.","solutions":["Use the static factories ofTopicIds / ofTopicNames to guarantee exactly one map is set.","If subclassing, ensure exactly one of the two maps is always provided.","Add constructor assertions in subclasses to fail fast with a clearer message."],"exampleFix":"// before\nnew DeleteTopicsResult(null, null);\n\n// after\nDeleteTopicsResult.ofTopicNames(nameMap);","handlingStrategy":"validation","validationCode":"// Ensure exactly one map is non-null\nif ((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 avoid passing null/null.","In subclass constructors, assert exactly one map is provided.","Review conditional map-selection logic to guarantee one branch is taken."],"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"}