{"id":"b62b07c3d5c053c7","repo":"apache/kafka","slug":"invalid-magic-value","errorCode":null,"errorMessage":"Invalid magic value {}","messagePattern":"Invalid magic value (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/record/internal/DefaultRecordBatch.java","lineNumber":478,"sourceCode":"    public static void writeHeader(ByteBuffer buffer,\n                                   long baseOffset,\n                                   int lastOffsetDelta,\n                                   int sizeInBytes,\n                                   byte magic,\n                                   CompressionType compressionType,\n                                   TimestampType timestampType,\n                                   long baseTimestamp,\n                                   long maxTimestamp,\n                                   long producerId,\n                                   short epoch,\n                                   int sequence,\n                                   boolean isTransactional,\n                                   boolean isControlBatch,\n                                   boolean isDeleteHorizonSet,\n                                   int partitionLeaderEpoch,\n                                   int numRecords) {\n        if (magic < RecordBatch.CURRENT_MAGIC_VALUE)\n            throw new IllegalArgumentException(\"Invalid magic value \" + magic);\n        if (baseTimestamp < 0 && baseTimestamp != NO_TIMESTAMP)\n            throw new IllegalArgumentException(\"Invalid message timestamp \" + baseTimestamp);\n\n        short attributes = computeAttributes(compressionType, timestampType, isTransactional, isControlBatch, isDeleteHorizonSet);\n\n        int position = buffer.position();\n        buffer.putLong(position + BASE_OFFSET_OFFSET, baseOffset);\n        buffer.putInt(position + LENGTH_OFFSET, sizeInBytes - LOG_OVERHEAD);\n        buffer.putInt(position + PARTITION_LEADER_EPOCH_OFFSET, partitionLeaderEpoch);\n        buffer.put(position + MAGIC_OFFSET, magic);\n        buffer.putShort(position + ATTRIBUTES_OFFSET, attributes);\n        buffer.putLong(position + BASE_TIMESTAMP_OFFSET, baseTimestamp);\n        buffer.putLong(position + MAX_TIMESTAMP_OFFSET, maxTimestamp);\n        buffer.putInt(position + LAST_OFFSET_DELTA_OFFSET, lastOffsetDelta);\n        buffer.putLong(position + PRODUCER_ID_OFFSET, producerId);\n        buffer.putShort(position + PRODUCER_EPOCH_OFFSET, epoch);\n        buffer.putInt(position + BASE_SEQUENCE_OFFSET, sequence);\n        buffer.putInt(position + RECORDS_COUNT_OFFSET, numRecords);","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/record/internal/DefaultRecordBatch.java#L460-L496","documentation":"Thrown by DefaultRecordBatch.writeHeader when the magic byte is less than RecordBatch.CURRENT_MAGIC_VALUE (V2 = 2). The v2 record format is the only one this writer supports; passing magic 0 or 1 (the legacy formats) is rejected because those use LegacyRecord encoding, not DefaultRecordBatch. IllegalArgumentException.","triggerScenarios":"Produced when writeHeader is called with magic=0 or magic=1 — e.g. a test or tool that builds a MemoryRecordsBuilder using a magic pulled from config/another record without validating it is V2, or code that copies a legacy record's magic into a new v2 batch. ByteBufferLogInputStream separately rejects magic outside [0,2] for inbound parsing.","commonSituations":"Cross-version tests that parameterize over magic values but reuse the v2 builder; downgrade attempts where a client tries to produce v0/v1 records to satisfy an old broker while routing through DefaultRecordBatch; copy-paste between LegacyRecord and DefaultRecordBatch code paths.","solutions":["Use RecordBatch.CURRENT_MAGIC_VALUE (V2) when calling writeHeader or MemoryRecords.builder.","If you must produce legacy v0/v1 records, route through the LegacyRecord / older MemoryRecordsBuilder paths, not DefaultRecordBatch.writeHeader.","Validate magic at the boundary: if (magic < RecordBatch.CURRENT_MAGIC_VALUE) throw or upgrade the broker rather than downgrade the wire format."],"exampleFix":"// before\nwriteHeader(buf, baseOffset, delta, size, /*magic*/ (byte) 1, ...);\n\n// after\nwriteHeader(buf, baseOffset, delta, size, RecordBatch.CURRENT_MAGIC_VALUE, ...);","handlingStrategy":"validation","validationCode":"// Magic is a writer-side argument. Validate against the supported set before writing:\nbyte requireValidMagic(byte magic) {\n    if (magic < RecordBatch.CURRENT_MAGIC_VALUE)   // CURRENT_MAGIC_VALUE == 2\n        throw new IllegalArgumentException(\"Unsupported magic \" + magic + \"; use RecordBatch.CURRENT_MAGIC_VALUE\");\n    return magic;\n}\n// Or, simplest: never pass magic explicitly — always use RecordBatch.CURRENT_MAGIC_VALUE.","typeGuard":"// Restrict magic to a fixed enum-like set:\nenum RecordMagic { V2((byte) 2);\n    final byte b; RecordMagic(byte b) { this.b = b; }\n    static RecordMagic fromByte(byte in) {\n        for (RecordMagic m : values()) if (m.b == in) return m;\n        throw new IllegalArgumentException(\"Unsupported magic \" + in);\n    }\n}","tryCatchPattern":"// Only relevant if you accept magic from external config:\ntry {\n    writeHeader(buf, magic, ...);\n} catch (IllegalArgumentException e) { // invalid magic\n    log.warn(\"Rejecting configured magic {}; falling back to CURRENT_MAGIC_VALUE\", magic, e);\n    writeHeader(buf, RecordBatch.CURRENT_MAGIC_VALUE, ...);\n}","preventionTips":["Hard-code magic to RecordBatch.CURRENT_MAGIC_VALUE unless you have a specific downgrade-compatibility reason.","Never read magic from untrusted user/config input without a whitelist check.","If supporting legacy v0/v1 batches, gate the code path behind a feature flag and test round-trip serialization."],"tags":["kafka","record-format","producer","magic","version","validation"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}