apache/iceberg · error · UnsupportedOperationException

Unsupported type: interval

Error message

Unsupported type: interval

What it means

Spark's CalendarInterval type has no corresponding Iceberg type, so StructInternalRow.getInterval always throws UnsupportedOperationException. This method exists only to satisfy Spark's InternalRow interface.

Solutions

  1. Do not attempt to read interval values from Iceberg rows — Iceberg has no interval type
  2. Rewrite the query to avoid projecting interval-typed values through the scan (compute intervals after materialization)
  3. If hit inside an expression, restructure so intervals are constructed in Spark, not read from the row

Example fix

// before
CalendarInterval iv = row.getInterval(ordinal);
// after
// construct in Spark instead of reading from Iceberg row
CalendarInterval iv = CalendarInterval.fromString("1 months 2 days");
Defensive patterns

Strategy: validation

Validate before calling

// Iceberg has no interval type; never request it from scan rows
if (sparkType instanceof CalendarIntervalType) {
  throw new IllegalArgumentException("Iceberg rows cannot supply CalendarInterval values");
}

Try / catch

try {
  return row.getInterval(ordinal);
} catch (UnsupportedOperationException e) {
  throw new UnsupportedOperationException("Build intervals in Spark, not from Iceberg rows", e);
}

Prevention

When it happens

Trigger: A Spark plan attempts to read an interval column from an Iceberg scan — e.g. a query projecting an interval-typed expression whose input is this row, or code incorrectly assuming interval support.

Common situations: Queries mixing interval literals/expressions with Iceberg scan output; custom code treating this row as a general-purpose interval container; accidental interval inference in a projection.

Related errors


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

Appendix: source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java:202

  }

  private byte[] getBinaryInternal(int ordinal) {
    Object bytes = struct.get(ordinal, 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 {
      throw new IllegalStateException(
          "Unknown type for binary field. Type name: " + bytes.getClass().getName());
    }
  }

  @Override
  public CalendarInterval getInterval(int ordinal) {
    throw new UnsupportedOperationException("Unsupported type: interval");
  }

  @Override
  public InternalRow getStruct(int ordinal, int numFields) {
    return isNullAt(ordinal) ? null : getStructInternal(ordinal);
  }

  private InternalRow getStructInternal(int ordinal) {
    return new StructInternalRow(
        type.fields().get(ordinal).type().asStructType(), struct.get(ordinal, StructLike.class));
  }

  @Override
  public ArrayData getArray(int ordinal) {
    return isNullAt(ordinal) ? null : getArrayInternal(ordinal);
  }

  private ArrayData getArrayInternal(int ordinal) {

View on GitHub (pinned to 86d9c8fc54)