{"id":"ad246f2bae74e83a","repo":"apache/kafka","slug":"the-topiccollection-topics-provided-did-not-mat","errorCode":null,"errorMessage":"The TopicCollection: {topics} provided did not match any supported classes for deleteTopics.","messagePattern":"The TopicCollection: (.+?) provided did not match any supported classes for deleteTopics\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java","lineNumber":2010,"sourceCode":"                // If there were any topics retries due to a quota exceeded exception, we propagate\n                // the initial error back to the caller if the request timed out.\n                maybeCompleteQuotaExceededException(options.shouldRetryOnQuotaViolation(),\n                    throwable, futures, quotaExceededExceptions, (int) (time.milliseconds() - now));\n                // Fail all the other remaining futures\n                completeAllExceptionally(futures.values(), throwable);\n            }\n        };\n    }\n\n    @Override\n    public DeleteTopicsResult deleteTopics(final TopicCollection topics,\n                                           final DeleteTopicsOptions options) {\n        if (topics instanceof TopicIdCollection)\n            return DeleteTopicsResult.ofTopicIds(handleDeleteTopicsUsingIds(((TopicIdCollection) topics).topicIds(), options));\n        else if (topics instanceof TopicNameCollection)\n            return DeleteTopicsResult.ofTopicNames(handleDeleteTopicsUsingNames(((TopicNameCollection) topics).topicNames(), options));\n        else\n            throw new IllegalArgumentException(\"The TopicCollection: \" + topics + \" provided did not match any supported classes for deleteTopics.\");\n    }\n\n    private Map<String, KafkaFuture<Void>> handleDeleteTopicsUsingNames(final Collection<String> topicNames,\n                                                                        final DeleteTopicsOptions options) {\n        final Map<String, KafkaFutureImpl<Void>> topicFutures = new HashMap<>(topicNames.size());\n        final List<String> validTopicNames = new ArrayList<>(topicNames.size());\n        for (String topicName : topicNames) {\n            if (topicNameIsUnrepresentable(topicName)) {\n                KafkaFutureImpl<Void> future = new KafkaFutureImpl<>();\n                future.completeExceptionally(new InvalidTopicException(\"The given topic name '\" +\n                    topicName + \"' cannot be represented in a request.\"));\n                topicFutures.put(topicName, future);\n            } else if (!topicFutures.containsKey(topicName)) {\n                topicFutures.put(topicName, new KafkaFutureImpl<>());\n                validTopicNames.add(topicName);\n            }\n        }\n        if (!validTopicNames.isEmpty()) {","sourceCodeStart":1992,"sourceCodeEnd":2028,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/admin/KafkaAdminClient.java#L1992-L2028","documentation":"Thrown by KafkaAdminClient.deleteTopics(TopicCollection, DeleteTopicsOptions) when the passed TopicCollection is neither a TopicIdCollection nor a TopicNameCollection. deleteTopics dispatches strictly on these two concrete subtypes (routing to handleDeleteTopicsUsingIds or handleDeleteTopicsUsingNames); any other implementation of TopicCollection is rejected immediately with IllegalArgumentException because there is no defined RPC mapping for it.","triggerScenarios":"Calling admin.deleteTopics(topicCollection, opts) where topicCollection is a custom subclass of TopicCollection, or null-extended in a way that fails both instanceof checks; or a test/mocked TopicCollection that doesn't extend TopicIdCollection/TopicNameCollection.","commonSituations":"Custom abstraction wrapping TopicCollection; passing null (would NPE earlier, but a no-op placeholder object triggers this); library/version mismatch where a subclass existed in an older fork; code that constructs TopicCollection via reflection incorrectly.","solutions":["Use the provided factories: TopicCollection.ofTopicNames(names) or TopicCollection.ofTopicIds(ids) to build the collection, or call the convenience admin.deleteTopics(Collection<String>) / admin.deleteTopics(TopicIdCollection).","If wrapping TopicCollection, extend TopicNameCollection or TopicIdCollection so the instanceof check succeeds.","Avoid passing custom/reflectively-built TopicCollection objects to the overloaded deleteTopics(TopicCollection, DeleteTopicsOptions) method."],"exampleFix":"// before - custom object, neither TopicIdCollection nor TopicNameCollection\nadmin.deleteTopics(myCustomTopicCollection, new DeleteTopicsOptions()); // throws\n\n// after - use a supported collection\nTopicCollection topics = TopicCollection.ofTopicNames(Arrays.asList(\"orders\",\"shipments\"));\nadmin.deleteTopics(topics, new DeleteTopicsOptions());","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean isSupportedTopicCollection(TopicCollection c) {\n    return c instanceof TopicIdCollection || c instanceof TopicNameCollection;\n}","tryCatchPattern":"if (!(topics instanceof TopicIdCollection || topics instanceof TopicNameCollection)) {\n    throw new IllegalArgumentException(\"Use TopicCollection.ofTopicNames(...) or TopicCollection.ofTopicIds(...)\");\n}\nadmin.deleteTopics(topics, options);","preventionTips":["Never subclass TopicCollection yourself; obtain instances only via TopicCollection.ofTopicNames(...) or TopicCollection.ofTopicIds(...).","If you accept TopicCollection from upstream code, narrow it to the two supported subtypes before calling deleteTopics.","Prefer the convenience overloads admin.deleteTopics(List<String>) / deleteTopics(TopicCollection) to avoid passing an unsupported type."],"tags":["admin-client","topic-management","argument-validation","api-contract"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}