apache/iceberg · error · IllegalArgumentException
Cannot convert to binary
Error message
Cannot convert to binary: ${value.getClass().getName()} What it means
RecordConverter.convertBase64Binary throws this IllegalArgumentException when a value targeted at an Iceberg binary column is neither a Base64-encoded String, byte[], nor ByteBuffer. The converter cannot wrap the given type into the expected ByteBuffer representation.
Solutions
- Declare the Connect field as bytes (SchemaBuilder.bytes()) or string (Base64) so the converter can decode it
- Wrap the raw value in ByteBuffer or byte[] via an SMT before it reaches the sink
- Inspect the offending value's actual class in the message and align the Iceberg column type with it
- If the data is really a struct/list, change the Iceberg table column type instead of binary
Example fix
// before Schema bad = SchemaBuilder.int64().build(); // long value -> cannot convert to binary // after Schema good = SchemaBuilder.bytes().build(); // byte[]/ByteBuffer accepted
Defensive patterns
Strategy: type-guard
Validate before calling
if (value != null && !(value instanceof String || value instanceof byte[] || value instanceof ByteBuffer)) {
throw new IllegalStateException("Binary field must be Base64 String, byte[], or ByteBuffer, got: " + value.getClass());
} Type guard
static boolean isBinaryCompatible(Object v) {
return v == null || v instanceof String || v instanceof byte[] || v instanceof ByteBuffer;
} Try / catch
try {
converter.convertValue(value, Types.BinaryType.get());
} catch (IllegalArgumentException e) {
log.error("Binary conversion failed for class: " + e.getMessage(), e);
// DLQ record or convert via ByteBuffer.wrap(String.valueOf(value).getBytes(StandardCharsets.UTF_8))
} Prevention
- Map binary columns to bytes or Base64 string Connect schemas
- Validate schemas against the Iceberg table at connector startup
- Avoid passing structs/lists into binary columns
- Keep Base64 encoding consistent between producer and sink
When it happens
Trigger: A binary Iceberg field receives a Number, Boolean, Map, List, or Struct from the Kafka Connect record instead of String/byte[]/ByteBuffer.
Common situations: Kafka Connect schema declares a field as int/struct while the Iceberg table expects binary; JSON-encoded binary arrives as a nested object; a schema evolution changed the field type on the producer side but not the Iceberg table (or vice versa).
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
- Cannot convert date
- Cannot convert time
- Cannot convert timestamp
- Cannot convert timestamptz
- Cannot convert to double
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/3289407fd1eb74b8.
Report an issue: GitHub.
Appendix: source
Thrown at kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java:536
if (FileFormat.PARQUET
.name()
.toLowerCase(Locale.ROOT)
.equals(config.writeProps().get(TableProperties.DEFAULT_FILE_FORMAT))) {
return UUIDUtil.convert(uuid);
} else {
return uuid;
}
}
protected ByteBuffer convertBase64Binary(Object value) {
if (value instanceof String) {
return ByteBuffer.wrap(Base64.getDecoder().decode((String) value));
} else if (value instanceof byte[]) {
return ByteBuffer.wrap((byte[]) value);
} else if (value instanceof ByteBuffer) {
return (ByteBuffer) value;
}
throw new IllegalArgumentException("Cannot convert to binary: " + value.getClass().getName());
}
@SuppressWarnings("JavaUtilDate")
protected LocalDate convertDateValue(Object value) {
if (value instanceof Number) {
int days = ((Number) value).intValue();
return DateTimeUtil.dateFromDays(days);
} else if (value instanceof String) {
return LocalDate.parse((String) value);
} else if (value instanceof LocalDate) {
return (LocalDate) value;
} else if (value instanceof Date) {
int days = (int) (((Date) value).getTime() / 1000 / 60 / 60 / 24);
return DateTimeUtil.dateFromDays(days);
}
throw new ConnectException("Cannot convert date: " + value);
}
View on GitHub (pinned to 86d9c8fc54)