{"id":"ee1f76b3cc7669d2","repo":"apache/kafka","slug":"record-batch-for-partition-at-offset-is-inva","errorCode":null,"errorMessage":"Record batch for partition {} at offset {} is invalid, cause: {}","messagePattern":"Record batch for partition (.+?) at offset (.+?) is invalid, cause: (.+?)","errorType":"exception","errorClass":"KafkaException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/internals/CompletedFetch.java","lineNumber":163,"sourceCode":"        if (!isConsumed) {\n            maybeCloseRecordStream();\n            cachedRecordException = null;\n            this.isConsumed = true;\n            recordAggregatedMetrics(bytesRead, recordsRead);\n\n            // we move the partition to the end if we received some bytes. This way, it's more likely that partitions\n            // for the same topic can remain together (allowing for more efficient serialization).\n            if (bytesRead > 0)\n                subscriptions.movePartitionToEnd(partition);\n        }\n    }\n\n    private void maybeEnsureValid(FetchConfig fetchConfig, RecordBatch batch) {\n        if (fetchConfig.checkCrcs && batch.magic() >= RecordBatch.MAGIC_VALUE_V2) {\n            try {\n                batch.ensureValid();\n            } catch (CorruptRecordException e) {\n                throw new KafkaException(\"Record batch for partition \" + partition + \" at offset \" +\n                        batch.baseOffset() + \" is invalid, cause: \" + e.getMessage());\n            }\n        }\n    }\n\n    private void maybeEnsureValid(FetchConfig fetchConfig, Record record) {\n        if (fetchConfig.checkCrcs) {\n            try {\n                record.ensureValid();\n            } catch (CorruptRecordException e) {\n                throw new KafkaException(\"Record for partition \" + partition + \" at offset \" + record.offset()\n                        + \" is invalid, cause: \" + e.getMessage());\n            }\n        }\n    }\n\n    private void maybeCloseRecordStream() {\n        if (records != null) {","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CompletedFetch.java#L145-L181","documentation":"KafkaException wrapping a CorruptRecordException, thrown by CompletedFetch.maybeEnsureValid(FetchConfig, RecordBatch) at CompletedFetch.java:163 when check.crcs is enabled (default true) and a v2+ record batch fails its CRC32C check via batch.ensureValid(). The CRC covers the entire batch payload, so a mismatch means the batch was altered after the producer wrote it — typically disk or network corruption. The original CorruptRecordException's message is appended as the cause.","triggerScenarios":"consumer.poll(...) with check.crcs=true (the default) returns a record batch whose recomputed CRC32C does not match the stored value. Validation runs from nextFetchedRecord at CompletedFetch.java:206 each time a new batch is taken from the iterator.","commonSituations":"Broker disk or page-cache bit-rot; faulty NIC, cable, switch, or RAM flipping bits in transit; partial segment writes after a broker crash; rare client/broker message-format skew; hardware fault on the producing path that wrote a bad batch.","solutions":["Verify broker disk health and inspect broker logs for write/checksum errors; a hardware fault is the most common root cause.","Skip the corrupt batch by seeking past it: consumer.seek(partition, batchEndOffset + 1), accepting loss of that batch's records.","If possible, force leadership to a healthy replica and let the consumer re-fetch from there.","Use kafka-dump-log on the broker segment to confirm corruption and decide whether to restore from snapshot or delete the bad segment."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    ConsumerRecords<K, V> recs = consumer.poll(Duration.ofSeconds(1));\n} catch (KafkaException e) {\n    if (e.getCause() instanceof CorruptRecordException || e.getMessage().contains(\"is invalid\")) {\n        TopicPartition tp = affectedPartition;          // track from records/partition\n        long next = consumer.position(tp);              // baseOffset of bad batch\n        consumer.seek(tp, next + 1);                     // skip past corrupt batch\n    } else throw e;\n}","preventionTips":["Keep check.crcs = true (the default) so corruption is detected rather than silently consumed.","On a corrupt-batch error, seek past baseOffset+1 to resume; do not retry the same offset.","Recurring CRC failures indicate disk or network faults — investigate the broker/hardware.","Never disable CRC checking in production to 'make the error go away'."],"tags":["consumer","corruption","crc","records"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}