apache/kafka · error · IllegalStateException
MockConsumer didn't have beginning offset specified, but tri
Error message
MockConsumer didn't have beginning offset specified, but tried to seek to beginning
What it means
Thrown by MockConsumer.resetOffsetPosition when an offset reset is needed (no committed offset) with strategy EARLIEST, but the mock has no beginning offset seeded for that partition. The mock cannot fabricate a beginning offset (it has no broker), so the test must seed one. Mirrors the real consumer's NoOffsetForPartition behavior but specific to the missing seed.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/MockConsumer.java:742
private void updateFetchPosition(TopicPartition tp) {
if (subscriptions.isOffsetResetNeeded(tp)) {
resetOffsetPosition(tp);
} else if (!committed.containsKey(tp)) {
subscriptions.requestOffsetReset(tp);
resetOffsetPosition(tp);
} else {
subscriptions.seek(tp, committed.get(tp).offset());
}
}
private void resetOffsetPosition(TopicPartition tp) {
AutoOffsetResetStrategy strategy = subscriptions.resetStrategy(tp);
Long offset;
if (strategy == AutoOffsetResetStrategy.EARLIEST) {
offset = beginningOffsets.get(tp);
if (offset == null)
throw new IllegalStateException("MockConsumer didn't have beginning offset specified, but tried to seek to beginning");
} else if (strategy == AutoOffsetResetStrategy.LATEST) {
offset = endOffsets.get(tp);
if (offset == null)
throw new IllegalStateException("MockConsumer didn't have end offset specified, but tried to seek to end");
} else if (strategy.type() == AutoOffsetResetStrategy.StrategyType.BY_DURATION) {
offset = durationResetOffsets.get(tp);
if (offset == null)
throw new IllegalStateException("MockConsumer didn't have duration offset specified, but tried to seek to timestamp");
} else {
throw new NoOffsetForPartitionException(tp);
}
seek(tp, offset);
}
@Override
public List<PartitionInfo> partitionsFor(String topic, Duration timeout) {
return partitionsFor(topic);
}View on GitHub (pinned to 996fb4585a)
Solutions
- Call mock.updateBeginningOffsets(Map.of(tp, 0L)) for partitions consumed with earliest reset.
- If you do not need reset behavior, commit an offset for the partition so reset is not triggered.
- Seed both beginning and end offsets whenever auto.offset.reset may apply.
Example fix
// before props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); mock.assign(Set.of(tp)); mock.poll(Duration.ofMillis(100)); // throws: no beginning offset // after mock.assign(Set.of(tp)); mock.updateBeginningOffsets(Map.of(tp, 0L)); mock.poll(Duration.ofMillis(100));
Defensive patterns
Strategy: validation
Validate before calling
// ensure a beginning offset exists for any partition consumed with earliest reset
for (TopicPartition tp : mockConsumer.assignment()) {
if (!seededBeginningOffsets.containsKey(tp))
mockConsumer.updateBeginningOffsets(Map.of(tp, 0L));
} Type guard
static boolean earliestResetCovered(MockConsumer<?,?> m, Set<TopicPartition> tps) {
return knownBeginningSeed.containsAll(tps);
} Try / catch
try {
return mockConsumer.poll(Duration.ofMillis(100));
} catch (IllegalStateException e) {
if ("MockConsumer didn't have beginning offset specified, but tried to seek to beginning".equals(e.getMessage())) {
mockConsumer.updateBeginningOffsets(currentAssignment().stream().collect(Collectors.toMap(tp -> tp, tp -> 0L)));
return mockConsumer.poll(Duration.ofMillis(100));
}
throw e;
} Prevention
- Seed beginning offsets whenever auto.offset.reset=earliest may apply.
- Commit offsets explicitly when you want to bypass reset behavior.
- Add a setup helper that seeds both beginning and end offsets for the assignment.
When it happens
Trigger: Consuming from a partition with no committed offset and auto.offset.reset=earliest, without calling updateBeginningOffsets for that partition; tests that rely on offset reset but forgot to seed the corresponding boundary.
Common situations: Tests for reset behavior that seed only end offsets; refactor that changed default reset strategy to earliest without seeding beginnings; assignment of new partitions after a rebalance without seeding.
Related errors
- You can only check the position for partitions assigned to t
- The partition {} does not have a beginning offset.
- The partition {} does not have an end offset.
- Cannot lose partitions that are not currently assigned: {not
- Cannot add records for a partition that is not assigned to t
AI-assisted analysis of apache/kafka@996fb4585a (2026-08-11).
Data as JSON: /api/errors/7eafb345cfb6fb03.
Report an issue: GitHub.