apache/kafka · error · IllegalArgumentException

seek offset must not be a negative number

Error message

seek offset must not be a negative number

What it means

Thrown by seek(TopicPartition, long offset) when offset < 0. Kafka offsets are non-negative log positions; a negative offset is meaningless and would corrupt subscription fetch positions, so it is rejected before any subscription state mutation. The guard sits outside the acquireAndEnsureOpen lock so it fails fast.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/internals/ClassicKafkaConsumer.java:797

    }

    @Override
    public void commitAsync(final Map<TopicPartition, OffsetAndMetadata> offsets, OffsetCommitCallback callback) {
        acquireAndEnsureOpen();
        try {
            throwIfGroupIdNotDefined();
            log.debug("Committing offsets: {}", offsets);
            offsets.forEach(this::updateLastSeenEpochIfNewer);
            coordinator.commitOffsetsAsync(new HashMap<>(offsets), callback);
        } finally {
            release();
        }
    }

    @Override
    public void seek(TopicPartition partition, long offset) {
        if (offset < 0)
            throw new IllegalArgumentException("seek offset must not be a negative number");

        acquireAndEnsureOpen();
        try {
            log.info("Seeking to offset {} for partition {}", offset, partition);
            SubscriptionState.FetchPosition newPosition = new SubscriptionState.FetchPosition(
                    offset,
                    Optional.empty(), // This will ensure we skip validation
                    this.metadata.currentLeader(partition));
            this.subscriptions.seekUnvalidated(partition, newPosition);
        } finally {
            release();
        }
    }

    @Override
    public void seek(TopicPartition partition, OffsetAndMetadata offsetAndMetadata) {
        long offset = offsetAndMetadata.offset();
        if (offset < 0) {

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Guard the offset before calling seek: if (offset < 0) use consumer.seekToBeginning / seekToEnd or position() instead.
  2. Fix the external offset store to return Optional.empty (or a clearly invalid sentinel handled explicitly) rather than -1.
  3. Initialize offsets to 0 (or use auto.offset.reset) so seek never receives a negative value.

Example fix

// before
long off = offsetStore.read(topic, partition); // returns -1 when missing
consumer.seek(new TopicPartition(topic, partition), off);

// after
long off = offsetStore.read(topic, partition);
TopicPartition tp = new TopicPartition(topic, partition);
if (off < 0) {
    consumer.seekToBeginning(Collections.singletonList(tp));
} else {
    consumer.seek(tp, off);
}
Defensive patterns

Strategy: validation

Validate before calling

// long offset = ...
if (offset < 0) {
    throw new IllegalArgumentException("seek offset must not be a negative number");
}
consumer.seek(partition, offset);

Type guard

static long requireNonNegativeOffset(long offset) {
    if (offset < 0) throw new IllegalArgumentException("seek offset must not be a negative number");
    return offset;
}

Try / catch

try {
    consumer.seek(partition, offset);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("negative number")) {
        consumer.seek(partition, 0L); // clamp to earliest
    } else throw e;
}

Prevention

When it happens

Trigger: Calling consumer.seek(partition, -1) or passing a computed offset that underflows/was not initialized. Reading an offset from a store that returns -1 as a sentinel and forwarding it directly.

Common situations: Offset store returning -1 (or another negative sentinel) when no committed offset exists. Arithmetic underflow. Misconfigured external offset store (file, DB, Redis) with a default of -1.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/3a653570bb73d9cc.json. Report an issue: GitHub.