apache/iceberg · error · UnsupportedOperationException

Not supported yet.

Error message

Not supported yet.

What it means

StructRowData.getRawValue implements the RowData API's RawValueData accessor, but this Iceberg-to-Flink adapter never supports raw (pass-through, non-deserialized) value access — it unconditionally throws UnsupportedOperationException('Not supported yet.'). Raw values are a Flink optimization that lets operators consume internal objects directly; Iceberg's StructLike-backed rows can't provide them.

Solutions

  1. Rewrite the consuming code to use the typed accessors (getInt/getLong/getString/getRow/...) instead of getRawValue.
  2. Configure the Flink operator/connector to not use raw value passthrough for Iceberg-sourced rows.
  3. Copy the field into a wrapper type and build RawValueData yourself if passthrough is essential: RawValueData.fromXxx(...).
  4. If you own the adapter, consider returning RawValueData of the boxed StructLike value, though typed access is the supported path.

Example fix

// before
MyType v = rowData.getRawValue(pos).toObject(MyType.class); // throws

// after
RowData inner = structRowData;
MyType v = (MyType) inner.getRow(pos, numFields); // typed access instead of raw value
Defensive patterns

Strategy: type-guard

Validate before calling

if (row instanceof StructRowData) {
  throw new IllegalStateException("Raw values not supported on Iceberg rows; use typed accessors");
}

Type guard

boolean supportsRawValues(RowData row) {
  return !(row instanceof StructRowData);
}

Try / catch

try {
  RawValueData<?> rv = row.getRawValue(pos);
} catch (UnsupportedOperationException e) {
  if ("Not supported yet.".equals(e.getMessage())) {
    // fall back to typed accessor for this field
    Object typed = readTypedValue(row, pos, fieldType);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Any code path calling getRawValue(pos) on a StructRowData — e.g. a Flink operator or function configured to use RawValueData / raw value passthrough on rows produced by an Iceberg scan.

Common situations: Custom Flink SourceFunction/ProcessFunction optimization that reads raw values; Flink connectors or state backends probing RowData for RawValueData support; generic RowData utility code exercising all accessors.

Related errors


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

Appendix: source

Thrown at flink/v2.2/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)