{"id":"19c391fd65b2ad39","repo":"apache/kafka","slug":"no-current-assignment-for-partition-tp","errorCode":null,"errorMessage":"No current assignment for partition ${tp}","messagePattern":"No current assignment for partition (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/internals/SubscriptionState.java","lineNumber":429,"sourceCode":"        else if (groupSubscription.containsAll(subscription))\n            return groupSubscription;\n        else {\n            // When subscription changes `groupSubscription` may be outdated, ensure that\n            // new subscription topics are returned.\n            Set<String> topics = new HashSet<>(groupSubscription);\n            topics.addAll(subscription);\n            return topics;\n        }\n    }\n\n    synchronized boolean needsMetadata(String topic) {\n        return subscription.contains(topic) || groupSubscription.contains(topic);\n    }\n\n    private TopicPartitionState assignedState(TopicPartition tp) {\n        TopicPartitionState state = this.assignment.stateValue(tp);\n        if (state == null)\n            throw new IllegalStateException(\"No current assignment for partition \" + tp);\n        return state;\n    }\n\n    private TopicPartitionState assignedStateOrNull(TopicPartition tp) {\n        return this.assignment.stateValue(tp);\n    }\n\n    public synchronized void seekValidated(TopicPartition tp, FetchPosition position) {\n        assignedState(tp).seekValidated(position);\n    }\n\n    public void seek(TopicPartition tp, long offset) {\n        seekValidated(tp, new FetchPosition(offset));\n    }\n\n    public void seekUnvalidated(TopicPartition tp, FetchPosition position) {\n        assignedState(tp).seekUnvalidated(position);\n    }","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/SubscriptionState.java#L411-L447","documentation":"Thrown by SubscriptionState.assignedState(TopicPartition) when the partition is not present in the consumer's current assignment (assignment.stateValue(tp) returns null). It is a programmer-error guard: any operation that needs an assigned partition (seek, position, commit, pause/resume) routes through assignedState, so calling them on an unassigned partition is illegal. The client never recovers from this internally; the caller must respect the consumer protocol (subscribe + poll, then operate).","triggerScenarios":"Calling consumer.seek(tp, offset), consumer.position(tp), consumer.committed(tp), consumer.pause(tp)/resume(tp), or requesting a reset for a TopicPartition that was never assigned to this consumer instance. Also seen when a rebalance revoked the partition between the last poll() and the subsequent call, or when using manual assignment (assign()) with a partition that is not in the cluster metadata yet.","commonSituations":"Mixing subscribe() with seek() before the first poll() returns assignments; caching TopicPartition references across rebalances without refreshing from consumer.assignment(); calling position() inside a ConsumerRebalanceListener before partitions are formally assigned; in the new async consumer, calling seek on a partition that the background thread has not yet wired up.","solutions":["Ensure consumer.poll() (or poll(Duration) in async API) has returned and consumer.assignment().contains(tp) is true before calling seek/position/pause.","Inside a ConsumerRebalanceListener, only invoke partition-scoped operations in onPartitionsAssigned, never in onPartitionsRevoked.","If using assign() manually, call consumer.partitionsFor(topic) first and only assign partitions that actually exist in the returned list.","Refresh any cached TopicPartition set after every rebalance instead of holding a stale collection."],"exampleFix":"// before\nconsumer.subscribe(Collections.singleton(\"orders\"));\nconsumer.seek(new TopicPartition(\"orders\", 0), 0); // throws: no assignment yet\n\n// after\nconsumer.subscribe(Collections.singleton(\"orders\"));\nconsumer.poll(Duration.ofMillis(500)); // triggers assignment\nif (consumer.assignment().contains(new TopicPartition(\"orders\", 0))) {\n    consumer.seek(new TopicPartition(\"orders\", 0), 0);\n}","handlingStrategy":"validation","validationCode":"// Operate on a partition only after confirming it is in the current assignment.\nSet<TopicPartition> assigned = consumer.assignment();\nif (!assigned.contains(tp)) {\n    // either wait for the next poll()/rebalance, or skip the per-partition op\n    return;\n}\nconsumer.seek(tp, offset); // safe: assignedState(tp) will resolve","typeGuard":"import org.apache.kafka.common.TopicPartition;\nimport java.util.Set;\n\n/** True iff tp is part of the consumer's live assignment (safe to seek/position/commit). */\nstatic boolean isAssigned(org.apache.kafka.clients.consumer.Consumer<?,?> c, TopicPartition tp) {\n    return tp != null && c.assignment().contains(tp);\n}","tryCatchPattern":"try {\n    consumer.seek(tp, offset);\n} catch (IllegalStateException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"No current assignment\")) {\n        // partition dropped in a rebalance: re-poll to refresh assignment, then retry or skip\n        consumer.poll(Duration.ofMillis(0));\n    } else {\n        throw e;\n    }\n}","preventionTips":["Only invoke seek/position/commit/offsetsForTimes on partitions returned by consumer.assignment().","Cache assignment right after poll() rather than holding stale TopicPartition refs across iterations.","Use a ConsumerRebalanceListener to invalidate local per-partition state on revoke.","Treat assignment as ephemeral: re-validate on every loop iteration after poll()."],"tags":["kafka","consumer","assignment","partition","illegal-state"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}