apache/iceberg · error · IllegalStateException
Unknown type for binary field. Type name: ${bytes.getClass()
Error message
Unknown type for binary field. Type name: ${bytes.getClass().getName()} What it means
getBinaryInternal extracts binary column values and only accepts ByteBuffer or byte[] from the underlying StructLike. Any other object type (String, Array[Byte] wrappers, custom types) throws IllegalStateException reporting the found class. It backs getBinary, getGeometry, getGeography, and binary view getters.
Source
Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java:195
CharSequence seq = struct.get(ordinal, CharSequence.class);
return UTF8String.fromString(seq.toString());
}
@Override
public byte[] getBinary(int ordinal) {
return isNullAt(ordinal) ? null : getBinaryInternal(ordinal);
}
private byte[] getBinaryInternal(int ordinal) {
Object bytes = struct.get(ordinal, Object.class);
// should only be either ByteBuffer or byte[]
if (bytes instanceof ByteBuffer) {
return ByteBuffers.toByteArray((ByteBuffer) bytes);
} else if (bytes instanceof byte[]) {
return (byte[]) bytes;
} else {
throw new IllegalStateException(
"Unknown type for binary field. Type name: " + bytes.getClass().getName());
}
}
@Override
public CalendarInterval getInterval(int ordinal) {
throw new UnsupportedOperationException("Unsupported type: interval");
}
@Override
public InternalRow getStruct(int ordinal, int numFields) {
return isNullAt(ordinal) ? null : getStructInternal(ordinal);
}
private InternalRow getStructInternal(int ordinal) {
return new StructInternalRow(
type.fields().get(ordinal).type().asStructType(), struct.get(ordinal, StructLike.class));
}View on GitHub (pinned to 86d9c8fc54)
Solutions
- Ensure binary-typed fields store ByteBuffer or byte[] in the StructLike
- Convert before read: wrap byte[] in ByteBuffer or copy the ByteBuffer via ByteBuffers.toByteArray yourself
- Use the message's class name to locate the offending producer and fix its conversion
- If you consume via getBinary, defensively fetch with get(ordinal, null) and normalize
Example fix
// before
byte[] b = row.getBinary(ordinal); // value is String
// after
Object raw = row.get(ordinal, null);
byte[] b = raw instanceof String
? ((String) raw).getBytes(StandardCharsets.UTF_8)
: row.getBinary(ordinal); Defensive patterns
Strategy: type-guard
Validate before calling
Object v = row.get(ordinal, null);
if (!(v instanceof ByteBuffer) && !(v instanceof byte[])) {
throw new IllegalStateException("Unexpected binary-field value: " + v.getClass());
} Type guard
boolean isBinaryCompatible(Object v) { return v instanceof ByteBuffer || v instanceof byte[]; } Try / catch
try {
return row.getBinary(ordinal);
} catch (IllegalStateException e) {
throw new IllegalStateException("Binary field held unexpected Java type", e);
} Prevention
- Always store binary as ByteBuffer or byte[]
- Avoid String-encoded binary in custom producers
- Cover binary/geometry columns in reader tests
When it happens
Trigger: A binary/geometry/geography column whose StructLike value is neither ByteBuffer nor byte[] — e.g. a custom producer storing UTF8String or a deserialization bug producing a wrong wrapper type.
Common situations: Custom readers or test fixtures populating binary fields with Strings; ORM/record adapters converting binary to unexpected Java types; geometry column values built by hand.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unknown type for binary field. Type name: " + bytes.getClass
- Unknown type for int field. Type name: ${integer.getClass().
- Unknown type for long field. Type name: ${longVal.getClass()
- Unknown type for int field. Type name: " + integer.getClass(
- Unknown type for long field. Type name: " + longVal.getClass
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/245a04906bc2dd70.
Report an issue: GitHub.