From 377bda4da3591051a3f357e246da28704ae965aa Mon Sep 17 00:00:00 2001 From: Anas Khan <83116240+anxkhn@users.noreply.github.com> Date: Sun, 5 Jul 2026 05:08:54 +0530 Subject: [PATCH] Core: Fix AvroEncoderUtil header error printing literal %02X AvroEncoderUtil.decode validated the magic bytes with Preconditions.checkState(cond, "Unrecognized header bytes: 0x%02X 0x%02X", header0, header1). Guava's Preconditions formats messages with Strings.lenientFormat, which only understands the %s placeholder, so the %02X specifiers were emitted verbatim and the two byte arguments were appended as decimal in a trailing bracket. A mismatched header therefore reported "Unrecognized header bytes: 0x%02X 0x%02X [16, 32]" instead of the intended hex, obscuring the actual bytes. Build the message with String.format(Locale.ROOT, ...) and pass it as the single %s argument, matching the existing handling in IcebergDecoder.decode. Add a regression test asserting the uppercase hex is rendered. Generated-by: opencode Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com> --- .../java/org/apache/iceberg/avro/AvroEncoderUtil.java | 6 +++--- .../org/apache/iceberg/avro/TestAvroEncoderUtil.java | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/apache/iceberg/avro/AvroEncoderUtil.java b/core/src/main/java/org/apache/iceberg/avro/AvroEncoderUtil.java index 0db8d7dd5f9f..97892bf8fcb2 100644 --- a/core/src/main/java/org/apache/iceberg/avro/AvroEncoderUtil.java +++ b/core/src/main/java/org/apache/iceberg/avro/AvroEncoderUtil.java @@ -23,6 +23,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.Locale; import org.apache.avro.LogicalTypes; import org.apache.avro.Schema; import org.apache.avro.io.BinaryDecoder; @@ -73,9 +74,8 @@ public static T decode(byte[] data) throws IOException { byte header1 = dataInput.readByte(); Preconditions.checkState( header0 == MAGIC_BYTES[0] && header1 == MAGIC_BYTES[1], - "Unrecognized header bytes: 0x%02X 0x%02X", - header0, - header1); + "%s", + String.format(Locale.ROOT, "Unrecognized header bytes: 0x%02X 0x%02X", header0, header1)); // Read avro schema Schema avroSchema = new Schema.Parser().parse(dataInput.readUTF()); diff --git a/core/src/test/java/org/apache/iceberg/avro/TestAvroEncoderUtil.java b/core/src/test/java/org/apache/iceberg/avro/TestAvroEncoderUtil.java index 456093501b72..0b853971706c 100644 --- a/core/src/test/java/org/apache/iceberg/avro/TestAvroEncoderUtil.java +++ b/core/src/test/java/org/apache/iceberg/avro/TestAvroEncoderUtil.java @@ -19,6 +19,7 @@ package org.apache.iceberg.avro; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.io.IOException; import java.util.List; @@ -27,6 +28,7 @@ import org.apache.avro.generic.GenericData; import org.apache.iceberg.data.DataTestBase; import org.apache.iceberg.types.Type; +import org.junit.jupiter.api.Test; public class TestAvroEncoderUtil extends DataTestBase { @Override @@ -68,4 +70,11 @@ protected void writeAndValidate(org.apache.iceberg.Schema schema) throws IOExcep assertThat(record.toString()).isEqualTo(expectedRecord.toString()); } } + + @Test + public void decodeRejectsUnrecognizedHeaderBytes() { + assertThatThrownBy(() -> AvroEncoderUtil.decode(new byte[] {(byte) 0x10, (byte) 0x20})) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Unrecognized header bytes: 0x10 0x20"); + } }