apache/iceberg · error · java.lang.UnsupportedOperationException

Not supported yet.

Error message

Not supported yet.

What it means

StructRowData.getRawValue(pos) is part of Flink's RowData contract for RawValueData access, but Iceberg's implementation does not support raw value access and throws UnsupportedOperationException unconditionally. Raw value semantics (pass-through binary) are not applicable to projected Iceberg struct rows.

Source

Thrown at flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/data/StructRowData.java:215

        LocalDateTime ldt = (LocalDateTime) timeVal;
        return TimestampData.fromEpochMillis(
            ldt.toInstant(ZoneOffset.UTC).toEpochMilli(), ldt.getNano() % 1_000_000);
      } else if (timeVal instanceof Long) {
        long timeLong = (Long) timeVal;
        return TimestampData.fromEpochMillis(
            Math.floorDiv(timeLong, 1_000_000L), (int) Math.floorMod(timeLong, 1_000_000L));
      } else {
        throw new IllegalStateException("Unknown type for timestamp_ns: " + timeVal.getClass());
      }
    }
    long timeLong = getLong(pos);
    return TimestampData.fromEpochMillis(
        Math.floorDiv(timeLong, 1000L), (int) Math.floorMod(timeLong, 1000L) * 1000);
  }

  @Override
  public <T> RawValueData<T> getRawValue(int pos) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public byte[] getBinary(int pos) {
    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);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Materialize the field via typed accessors (getInt/getLong/getString/getBinary) and construct RawValueData yourself if needed
  2. Ensure downstream operators don't call getRawValue on Iceberg-projected rows (e.g. wrap rows in GenericRowData)
  3. Reorder the pipeline so RawValueData usage happens before Iceberg projection wrapping

Example fix

// before
RawValueData<String> raw = structRowData.getRawValue(pos); // throws
// after
String s = structRowData.getString(pos);
RawValueData<String> raw = StringData.fromString(s);
Defensive patterns

Strategy: try-catch

Try / catch

try { RawValueData<T> raw = row.getRawValue(pos); } catch (UnsupportedOperationException e) { T value = typedAccessor(row, pos); raw = RawValueData.fromObject(value); }

Prevention

When it happens

Trigger: Calling getRawValue(...) on a StructRowData, e.g. from a Flink sink or operator that uses RawValueData APIs (such as some serialization paths or async sinks).

Common situations: Connecting Iceberg scan output directly to operators that call getRawValue on all RowData; generic RowData-processing utilities that touch every accessor.

Related errors


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