apache/iceberg · error · IllegalStateException

Unknown type for binary field. Type name:

Error message

Unknown type for binary field. Type name: 

What it means

StructRowData.getBinaryInternal converts a struct field to a Flink byte[], accepting byte[], ByteBuffer and UUID (converted to its 16-byte representation). Any other class raises this IllegalStateException. It indicates a binary-typed field holds an unexpected Java object.

Source

Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/data/StructRowData.java:238

    return isNullAt(pos) ? null : getBinaryInternal(pos);
  }

  private byte[] getBinaryInternal(int pos) {
    Object bytes = struct.get(pos, 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 if (bytes instanceof UUID) {
      UUID uuid = (UUID) bytes;
      ByteBuffer bb = ByteBuffer.allocate(16);
      bb.putLong(uuid.getMostSignificantBits());
      bb.putLong(uuid.getLeastSignificantBits());
      return bb.array();
    } else {
      throw new IllegalStateException(
          "Unknown type for binary field. Type name: " + bytes.getClass().getName());
    }
  }

  @Override
  public ArrayData getArray(int pos) {
    return isNullAt(pos)
        ? null
        : (ArrayData)
            convertValue(type.fields().get(pos).type().asListType(), struct.get(pos, List.class));
  }

  @Override
  public MapData getMap(int pos) {
    return isNullAt(pos)
        ? null
        : (MapData)
            convertValue(type.fields().get(pos).type().asMapType(), struct.get(pos, Map.class));

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Write binary fields as byte[]/ByteBuffer (or java.util.UUID for UUID-typed fields).
  2. If the value is a String, decode it (e.g. Base64/hex) to bytes before storing.
  3. Check the Flink type mapping: BINARY/VARBINARY columns must contain byte[] in the struct.

Example fix

// before
row.setField(pos, uuidString); // String

// after
UUID uuid = UUID.fromString(uuidString);
row.setField(pos, uuid); // supported by getBinaryInternal
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = struct.getField(pos);
if (!(v instanceof byte[] || v instanceof ByteBuffer || v instanceof UUID)) {
  throw new IllegalArgumentException("Unexpected class for binary field: " + v.getClass());
}

Type guard

boolean isBinaryCompatible(Object v) {
  return v instanceof byte[] || v instanceof ByteBuffer || v instanceof UUID;
}

Try / catch

try {
  byte[] b = rowData.getBinary(pos);
} catch (IllegalStateException e) {
  // decode the value (e.g. Base64 string -> bytes) and retry
}

Prevention

When it happens

Trigger: Calling getBinary(pos) (which delegates to getBinaryInternal) where the field value is not byte[], ByteBuffer, or UUID, e.g. a String or BigDecimal.

Common situations: Writers encoding binary/UUID data as Strings or hex text; UUID stored as String rather than java.util.UUID; fixed/decimal values routed into binary columns.

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/2bd31779d5ae5e5f. Report an issue: GitHub.