apache/kafka · error · KafkaException

Failed to make progress reading messages at {}={}. Received

Error message

Failed to make progress reading messages at {}={}. Received a non-empty fetch response from the server, but no complete records were found.

What it means

KafkaException raised in FetchCollector.handleInitializeSuccess when the fetch response carries a non-empty records payload (bytes > 0) but iterating the record batches yields zero batches. Per KIP-74 this is impossible for brokers that support FetchRequest/Response v4+, so it indicates a malformed response, a broker bug, or an intermediary (proxy/serde) that corrupted the bytes. The client refuses to silently lose data, so it throws rather than advance the offset.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/internals/FetchCollector.java:272

        final long fetchOffset = completedFetch.nextFetchOffset();

        // we are interested in this fetch only if the beginning offset matches the
        // current consumed position
        SubscriptionState.FetchPosition position = subscriptions.positionOrNull(tp);
        if (position == null || position.offset != fetchOffset) {
            log.debug("Discarding stale fetch response for partition {} since its offset {} does not match " +
                "the expected offset {} or the partition has been unassigned", tp, fetchOffset, position);
            return null;
        }

        final FetchResponseData.PartitionData partition = completedFetch.partitionData;
        log.trace("Preparing to read {} bytes of data for partition {} with offset {}",
                FetchResponse.recordsSize(partition), tp, position);
        Iterator<? extends RecordBatch> batches = FetchResponse.recordsOrFail(partition).batches().iterator();

        if (!batches.hasNext() && FetchResponse.recordsSize(partition) > 0) {
            // This should not happen with brokers that support FetchRequest/Response V4 or higher (i.e. KIP-74)
            throw new KafkaException("Failed to make progress reading messages at " + tp + "=" +
                    fetchOffset + ". Received a non-empty fetch response from the server, but no " +
                    "complete records were found.");
        }

        if (!updatePartitionState(partition, tp)) {
            return null;
        }

        completedFetch.setInitialized();
        return completedFetch;
    }

    private boolean updatePartitionState(final FetchResponseData.PartitionData partitionData,
                                         final TopicPartition tp) {
        if (partitionData.highWatermark() >= 0) {
            log.trace("Updating high watermark for partition {} to {}", tp, partitionData.highWatermark());
            if (!subscriptions.tryUpdatingHighWatermark(tp, partitionData.highWatermark())) {
                return false;

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Ensure all brokers are at version 0.10.0 or higher (FetchResponse v4+); decommission legacy brokers.
  2. Remove or fix any HTTP/TCP proxy, sidecar, or capture tool between the client and brokers that may alter the response body.
  3. Upgrade kafka-clients to the latest release to benefit from stricter response validation and fixes.
  4. Capture a network trace (or enable TRACE logging of org.apache.kafka.clients.FetchCollector) to confirm the response bytes are intact end-to-end.

Example fix

// before: client points at mixed cluster with one 0.9 broker
bootstrap.servers=broker-v9:9092,broker-v3:9092

// after: all brokers >= 0.10 and client aligned to cluster version
bootstrap.servers=broker-v3:9092,broker-v3b:9092
# (decommission the 0.9 node)
Defensive patterns

Strategy: retry

Validate before calling

// This is a broker-version compatibility issue (KIP-74): the server returned bytes
// but no complete RecordBatch. You cannot validate it client-side. Ensure broker and
// client versions are aligned to avoid triggering it:
Properties p = new Properties();
p.put(ProducerConfig.BROKER_VERSION_COMPATIBILITY_ENABLE, "true"); // producer side
// On the consumer side, verify the broker reports a FetchRequest V4+ capable version:
Node node = consumer.partitionsFor("myTopic").get(0).leader();
// If node is null or the cluster is mid-upgrade, defer heavy consumption until stable.

Try / catch

int attempts = 0;
while (attempts++ < 3) {
    try {
        return consumer.poll(Duration.ofMillis(500));
    } catch (org.apache.kafka.common.KafkaException e) {
        if (e.getMessage() != null && e.getMessage().startsWith("Failed to make progress reading messages")) {
            // FetchCollector.java:272: non-empty response, zero complete batches.
            // Almost always a broker < FetchRequest V4 or a mid-upgrade/transient corruption.
            log.warn("Broker returned unparseable records for partition; retrying after metadata refresh (attempt {})", attempts);
            consumer.requestOffsetReset(consumer.assignment()); // optional: force re-fetch from a clean offset
            continue;
        }
        throw e;
    }
}
throw new IllegalStateException("Could not make fetch progress after retries");

Prevention

When it happens

Trigger: Triggered at FetchCollector.java:272 when FetchResponse.recordsSize(partition) > 0 but FetchResponse.recordsOrFail(partition).batches().iterator() has no next element.

Common situations: Talking to a down-level or buggy broker (< 0.10.0 / FetchResponse v3 or earlier); a misbehaving L7 proxy or sidecar that rewrites the fetch response; on-the-wire corruption from a faulty NIC / TLS terminator; broker version mismatch in a heterogeneous cluster; old broker mixed with new client during an upgrade.

Related errors


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