{"id":"18705fa03669b07c","repo":"apache/kafka","slug":"consumer-is-not-subscribed-to-any-topics","errorCode":null,"errorMessage":"Consumer is not subscribed to any topics.","messagePattern":"Consumer is not subscribed to any topics\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/internals/ShareConsumerImpl.java","lineNumber":615,"sourceCode":"\n        acquireAndEnsureOpen();\n        try {\n            // Throw any errors notified by the background thread\n            processBackgroundEvents();\n\n            // Handle any completed acknowledgements for which we already have the responses\n            handleCompletedAcknowledgements();\n\n            // If using implicit acknowledgement, acknowledge the previously fetched records\n            acknowledgeBatchIfImplicitAcknowledgement();\n\n            // If using explicit acknowledgement, make sure all in-flight records have been acknowledged\n            ensureInFlightAcknowledgedIfExplicitAcknowledgement();\n\n            kafkaShareConsumerMetrics.recordPollStart(timer.currentTimeMs());\n\n            if (subscriptions.hasNoSubscriptionOrUserAssignment()) {\n                throw new IllegalStateException(\"Consumer is not subscribed to any topics.\");\n            }\n\n            shouldSendShareFetchEvent = true;\n\n            // This distinguishes the first pass of the inner do/while loop from subsequent passes for the\n            // in-flight poll event logic.\n            boolean firstPass = true;\n\n            do {\n                // We must not allow wake-ups between polling for fetches and returning the records.\n                // A wake-up between returned fetches and returning records would lead to never\n                // returning the records in the fetches. Thus, we trigger a possible wake-up before we poll fetches.\n                wakeupTrigger.maybeTriggerWakeup();\n\n                // Make sure the network thread can tell the application is actively polling\n                checkInFlightPoll(timer, firstPass);\n                firstPass = false;\n                final ShareFetch<K, V> fetch = pollForFetches(timer);","sourceCodeStart":597,"sourceCodeEnd":633,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ShareConsumerImpl.java#L597-L633","documentation":"Thrown by ShareConsumerImpl.poll (line 615) when subscriptions.hasNoSubscriptionOrUserAssignment() returns true at poll time. The share consumer requires either an active topic subscription or a user assignment before records can be fetched, mirroring the contract of the classic KafkaConsumer. Without a subscription the broker has no share group assignment to honor, so polling is meaningless and the client fails fast rather than blocking forever.","triggerScenarios":"Calling consumer.poll(...) on a ShareConsumer (KafkaShareConsumer) before calling consumer.subscribe(...) or consumer.assign(...). Also triggered after consumer.unsubscribe() is invoked and then poll() is called without re-subscribing.","commonSituations":"App boot sequences where poll() runs in a loop started before the subscribe call completes; refactors that move subscribe() into a conditional branch that was skipped; test harnesses that construct the consumer and immediately poll; misconfigured dependency-injection where the subscribe step was wired to a different bean than the poll loop.","solutions":["Ensure consumer.subscribe(Collections.singletonList(topic)) is called before the first poll().","If you intentionally unsubscribed, do not call poll() again until you re-subscribe or assign partitions.","Guard the poll loop with a check on whether a subscription/assignment exists, or initialize the subscription in the constructor/@PostConstruct of the owning component.","Verify the subscribe() call is not inside a try block that silently swallowed an earlier exception, leaving the consumer un-subscribed."],"exampleFix":"// before\ntry (var consumer = new KafkaShareConsumer<String,String>(props)) {\n    ConsumerRecords<String,String> records = consumer.poll(Duration.ofMillis(1000));\n}\n\n// after\ntry (var consumer = new KafkaShareConsumer<String,String>(props)) {\n    consumer.subscribe(Collections.singletonList(\"orders\"));\n    ConsumerRecords<String,String> records = consumer.poll(Duration.ofMillis(1000));\n}","handlingStrategy":"validation","validationCode":"// Before calling poll(), ensure the consumer has a subscription or assignment.\njava.util.Set<String> sub = consumer.subscription();\njava.util.Set<org.apache.kafka.common.TopicPartition> asn = consumer.assignment();\nif ((sub == null || sub.isEmpty()) && (asn == null || asn.isEmpty())) {\n    throw new IllegalStateException(\"Cannot poll: consumer has no subscription and no assignment\");\n}","typeGuard":"null","tryCatchPattern":"try {\n    org.apache.kafka.clients.consumer.ConsumerRecords<K,V> records = consumer.poll(java.time.Duration.ofMillis(500));\n} catch (IllegalStateException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"not subscribed\")) {\n        // ensure subscription is established before retrying\n        consumer.subscribe(java.util.List.of(\"my-topic\"));\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always call consumer.subscribe(Collections) or assign(partitions) before the first poll().","Treat subscription as a precondition in a wrapper method that asserts a non-empty subscription set.","If you unsubscribe at runtime, gate subsequent poll() calls behind a state flag."],"tags":["share-consumer","subscription","poll","kafka-client"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}