apache/iceberg · error · IllegalStateException

Unknown type for binary field. Type name: ${className}

Error message

Unknown type for binary field. Type name: ${className}

What it means

StructRowData.getBinaryInternal expects a field value that is either byte[], ByteBuffer, or java.util.UUID (fixed-length Iceberg UUID). Any other in-memory representation of a binary/fixed field triggers this IllegalStateException, signaling an internal representation bug rather than user error.

Source

Thrown at flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/data/StructRowData.java:237

    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. Inspect bytes.getClass().getName() in the message and ensure the field value stored in the struct is byte[], ByteBuffer, or UUID.
  2. Fix or update the value reader/writer that populates the struct so binary fields are stored in one of the supported types.
  3. Convert the offending object to byte[] before storing it in the struct (e.g. ByteBuffer.array() or UUID→16-byte encoding as done in getBinaryInternal).

Example fix

// before
Object value = storedUnknownType; // e.g. String
struct.set(pos, value);
// after
byte[] bytes = ((ByteBuffer) value).array(); // normalize before storing
struct.set(pos, bytes);
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = struct.get(pos, Object.class);
if (v != null && !(v instanceof byte[]) && !(v instanceof ByteBuffer) && !(v instanceof java.util.UUID)) {
  throw new IllegalStateException("Unsupported binary field type: " + v.getClass());
}

Type guard

boolean isSupportedBinary(Object v) { return v == null || v instanceof byte[] || v instanceof ByteBuffer || v instanceof java.util.UUID; }

Try / catch

try { return rowData.getBinary(pos); } catch (IllegalStateException e) { return normalizeToBytes(struct.get(pos, Object.class)); }

Prevention

When it happens

Trigger: Calling getBinary(pos) on a StructRowData whose stored value for pos is a Java object of an unexpected class (neither byte[], ByteBuffer, nor UUID) — e.g. after a schema/representation mismatch or a custom reader that stores binary fields in a different type.

Common situations: Custom value readers or third-party integrations that put unexpected objects into the struct; version mismatches where the reader produced a different internal type for fixed/uuid columns.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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