{"record":{"id":"282875bdf05542cd","repo":"apache/kafka","slug":"mockconsumer-didn-t-have-duration-offset-specified","errorCode":null,"errorMessage":"MockConsumer didn't have duration offset specified, but tried to seek to timestamp","messagePattern":"MockConsumer didn't have duration offset specified, but tried to seek to timestamp","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/MockConsumer.java","lineNumber":750,"sourceCode":"            subscriptions.seek(tp, committed.get(tp).offset());\n        }\n    }\n\n    private void resetOffsetPosition(TopicPartition tp) {\n        AutoOffsetResetStrategy strategy = subscriptions.resetStrategy(tp);\n        Long offset;\n        if (strategy == AutoOffsetResetStrategy.EARLIEST) {\n            offset = beginningOffsets.get(tp);\n            if (offset == null)\n                throw new IllegalStateException(\"MockConsumer didn't have beginning offset specified, but tried to seek to beginning\");\n        } else if (strategy == AutoOffsetResetStrategy.LATEST) {\n            offset = endOffsets.get(tp);\n            if (offset == null)\n                throw new IllegalStateException(\"MockConsumer didn't have end offset specified, but tried to seek to end\");\n        } else if (strategy.type() == AutoOffsetResetStrategy.StrategyType.BY_DURATION) {\n            offset = durationResetOffsets.get(tp);\n            if (offset == null)\n                throw new IllegalStateException(\"MockConsumer didn't have duration offset specified, but tried to seek to timestamp\");\n        } else {\n            throw new NoOffsetForPartitionException(tp);\n        }\n        seek(tp, offset);\n    }\n\n    @Override\n    public List<PartitionInfo> partitionsFor(String topic, Duration timeout) {\n        return partitionsFor(topic);\n    }\n\n    @Override\n    public Map<String, List<PartitionInfo>> listTopics(Duration timeout) {\n        return listTopics();\n    }\n\n    @Override\n    public Map<TopicPartition, OffsetAndTimestamp> offsetsForTimes(Map<TopicPartition, Long> timestampsToSearch,","sourceCodeStart":732,"sourceCodeEnd":768,"githubUrl":"https://github.com/apache/kafka/blob/996fb4585aa1bcc8980b0e1b8d6b168b986cd979/clients/src/main/java/org/apache/kafka/clients/consumer/MockConsumer.java#L732-L768","documentation":"Same MockConsumer reset path as the LATEST/BEGINNING cases, but for OffsetResetStrategy.BY_DURATION (timestamp-based reset). MockConsumer consults its durationResetOffsets map; if the test never seeded a timestamp->offset mapping for the partition via updateDurationOffsets(...), it throws this IllegalStateException instead of seeking.","triggerScenarios":"Subscription configured with an assignor/strategy whose reset type is BY_DURATION, the partition has no committed offset, and the test never called mockConsumer.updateDurationOffsets(Map.of(tp, offset)) for that partition; poll()/position() then enters resetOffsetPosition(tp) with strategy.type() == BY_DURATION.","commonSituations":"New tests exercising timestamp-based auto offset reset; copy-pasting an EARLIEST/LATEST test setup and forgetting the duration seed; or asserting offsetsForTimes flow where the reset path is triggered as a side effect.","solutions":["Call mockConsumer.updateDurationOffsets(Map.of(tp, <offsetAtTimestamp>)) for every partition before the first poll that may trigger a reset.","Switch the strategy to EARLIEST or LATEST and use updateBeginningOffsets/updateEndOffsets if duration-based reset is not the behavior under test.","Provide a committed offset or call seek(tp, offset) so resetOffsetPosition is bypassed."],"exampleFix":"// before\nMockConsumer<byte[],byte[]> c = new MockConsumer<>(OffsetResetStrategy.BY_DURATION);\nc.subscribe(Collections.singleton(\"t\"));\nc.poll(Duration.ofMillis(0)); // -> IllegalStateException\n\n// after\nMockConsumer<byte[],byte[]> c = new MockConsumer<>(OffsetResetStrategy.BY_DURATION);\nc.updateDurationOffsets(Map.of(new TopicPartition(\"t\",0), 5L));\nc.subscribe(Collections.singleton(\"t\"));\nc.poll(Duration.ofMillis(0));","handlingStrategy":"validation","validationCode":"// Ensure duration offsets are seeded for any partition that may reset by duration.\nif (mockConsumer.currentStrategy() == OffsetResetStrategy.BY_DURATION) {\n    Map<TopicPartition, Long> seed = assigned.stream()\n        .collect(Collectors.toMap(tp -> tp, tp -> 0L));\n    mockConsumer.updateDurationOffsets(seed);\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["When constructing MockConsumer with BY_DURATION, always call updateDurationOffsets before poll.","Keep a single setup helper that seeds beginning, end, and duration offsets defensively."],"tags":["testing","mock","consumer","offset-reset","timestamp","kafka-clients"],"backgroundTag":null,"analyzedSha":"996fb4585aa1bcc8980b0e1b8d6b168b986cd979","analyzedAt":"2026-08-11T22:03:28.655Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}