{"id":"39984f5eefd334c0","repo":"apache/kafka","slug":"record-for-partition-at-offset-is-invalid-c","errorCode":null,"errorMessage":"Record for partition {} at offset {} is invalid, cause: {}","messagePattern":"Record 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":174,"sourceCode":"    }\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) {\n            records.close();\n            records = null;\n        }\n    }\n\n    private Record nextFetchedRecord(FetchConfig fetchConfig) {\n        while (true) {\n            if (records == null || !records.hasNext()) {\n                maybeCloseRecordStream();\n\n                if (!batches.hasNext()) {","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/CompletedFetch.java#L156-L192","documentation":"KafkaException wrapping a CorruptRecordException, thrown by CompletedFetch.maybeEnsureValid(FetchConfig, Record) at CompletedFetch.java:174 when check.crcs is enabled and a single legacy-format (message magic v0/v1) record fails its per-record CRC check via record.ensureValid(). Unlike v2 batches where the CRC lives on the batch, pre-v2 messages carry a per-record checksum, so this path only fires on topics still stored in the old format.","triggerScenarios":"consumer.poll(...) with check.crcs=true reading a legacy v0/v1 message whose individual CRC does not match its payload. Validation is invoked from nextFetchedRecord at CompletedFetch.java:232 for each record returned to the user.","commonSituations":"Topics still on v0/v1 message format because inter.broker.protocol.version / log.message.format.version are pinned low on the broker; reading historical segments produced before a format upgrade; same hardware-level corruption sources as the v2 batch case; downgrade scenarios after a failed format migration.","solutions":["Skip the corrupt record: consumer.seek(partition, record.offset() + 1) and resume polling.","Inspect broker disk and network health; checksum failures almost always indicate hardware faults.","Plan a message-format upgrade to v2 once all clients are compatible, so per-record CRCs are replaced by batch-level coverage.","If the segment is unrecoverable, restore from backup or use kafka-dump-log to confirm before deleting 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.getMessage().contains(\"Record for partition\")) {\n        TopicPartition tp = affectedPartition;\n        long badOffset = consumer.position(tp);\n        consumer.seek(tp, badOffset + 1);   // skip the single poison-pill record\n    } else throw e;\n}","preventionTips":["Treat a per-record CRC error as a poison pill: seek past record.offset()+1 to continue.","Log the topic/partition/offset so the producer or storage layer can be investigated.","Track skip counts in metrics — a rising rate signals systemic corruption.","Do not loop indefinitely on the same bad record; always advance the position."],"tags":["consumer","corruption","crc","legacy"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}