apache/kafka · error · TimeoutException

Timeout of {}ms expired before the last committed offset for

Error message

Timeout of {}ms expired before the last committed offset for partitions {} could be determined. Try tuning {} larger to relax the threshold.

What it means

Thrown by KafkaConsumer.committed(Set, Duration) when the group coordinator returns null within the timeout, meaning committed offsets could not be fetched in time. The message explicitly suggests tuning default.api.timeout.ms larger. A null result from coordinator.fetchCommittedOffsets indicates the request timed out or the coordinator was unavailable, not that offsets are absent (absent offsets come back as a map with null values).

Source

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

            release();
        }
    }

    @Override
    public Map<TopicPartition, OffsetAndMetadata> committed(final Set<TopicPartition> partitions) {
        return committed(partitions, Duration.ofMillis(defaultApiTimeoutMs));
    }

    @Override
    public Map<TopicPartition, OffsetAndMetadata> committed(final Set<TopicPartition> partitions, final Duration timeout) {
        acquireAndEnsureOpen();
        long start = time.nanoseconds();
        try {
            throwIfGroupIdNotDefined();
            final Map<TopicPartition, OffsetAndMetadata> offsets;
            offsets = coordinator.fetchCommittedOffsets(partitions, time.timer(timeout));
            if (offsets == null) {
                throw new TimeoutException("Timeout of " + timeout.toMillis() + "ms expired before the last " +
                        "committed offset for partitions " + partitions + " could be determined. Try tuning " +
                        ConsumerConfig.DEFAULT_API_TIMEOUT_MS_CONFIG + " larger to relax the threshold.");
            } else {
                offsets.forEach(this::updateLastSeenEpochIfNewer);
                return offsets;
            }
        } finally {
            kafkaConsumerMetrics.recordCommitted(time.nanoseconds() - start);
            release();
        }
    }

    @Override
    public Uuid clientInstanceId(Duration timeout) {
        if (clientTelemetryReporter.isEmpty()) {
            throw new IllegalStateException("Telemetry is not enabled. Set config `" + ConsumerConfig.ENABLE_METRICS_PUSH_CONFIG + "` to `true`.");

        }

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Increase default.api.timeout.ms in consumer config as the message suggests.
  2. Pass an explicit larger Duration: consumer.committed(tps, Duration.ofMinutes(2)).
  3. Retry with backoff on TimeoutException; ensure group coordinator is reachable and stable.
  4. Confirm group.id is set and the coordinator node is not under heavy load or in the middle of a rebalance.

Example fix

// before
Map<TopicPartition, OffsetAndMetadata> c = consumer.committed(tps);

// after
props.put(ConsumerConfig.DEFAULT_API_TIMEOUT_MS_CONFIG, 120000);
Map<TopicPartition, OffsetAndMetadata> c = consumer.committed(tps, Duration.ofMinutes(2));
Defensive patterns

Strategy: retry

Validate before calling

// Validate inputs you control, then call with an explicit, oversized timeout:
if (partitions == null || partitions.isEmpty()) return Map.of();
Duration timeout = Duration.ofMillis(
    Math.max(defaultApiTimeoutMs, 60_000));
consumer.committed(partitions, timeout);

Try / catch

// Retry committed() with a larger timeout; the message itself points at DEFAULT_API_TIMEOUT_MS_CONFIG:
try {
    return consumer.committed(partitions, Duration.ofSeconds(60));
} catch (TimeoutException e) {
    log.warn("committed() timed out, retrying with 120s", e);
    return consumer.committed(partitions, Duration.ofSeconds(120));
}

Prevention

When it happens

Trigger: Calling committed() with a group.id set but the coordinator unreachable; coordinator loading or in transition; network slow; default.api.timeout.ms too small for the cluster; calling committed() immediately after subscribe() before FindCoordinator completes.

Common situations: Cloud deployments with high latency to brokers; large consumer groups during coordinator failover; default.api.timeout.ms left at default (often 60s) but overridden lower; using committed() in health checks that run on a tight timer.

Related errors


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