apache/iceberg · error · IllegalArgumentException

Cannot create expression literal from %s: %s

Error message

Cannot create expression literal from %s: %s

What it means

Literals.from(Object) converts a Java value into an Iceberg expression Literal, but only for the supported value types (Boolean, Integer, Long, Float, Double, String, byte[]/ByteBuffer, UUID, CharSequence-based types, BigDecimal, Variant, etc.). For any other object type it throws IllegalArgumentException naming the class and value. It means the value's type has no corresponding Iceberg literal representation.

Source

Thrown at api/src/main/java/org/apache/iceberg/expressions/Literals.java:92

    } else if (value instanceof Float) {
      return (Literal<T>) new Literals.FloatLiteral((Float) value);
    } else if (value instanceof Double) {
      return (Literal<T>) new Literals.DoubleLiteral((Double) value);
    } else if (value instanceof CharSequence) {
      return (Literal<T>) new Literals.StringLiteral((CharSequence) value);
    } else if (value instanceof UUID) {
      return (Literal<T>) new Literals.UUIDLiteral((UUID) value);
    } else if (value instanceof byte[]) {
      return (Literal<T>) new Literals.FixedLiteral(ByteBuffer.wrap((byte[]) value));
    } else if (value instanceof ByteBuffer) {
      return (Literal<T>) new Literals.BinaryLiteral((ByteBuffer) value);
    } else if (value instanceof BigDecimal) {
      return (Literal<T>) new Literals.DecimalLiteral((BigDecimal) value);
    } else if (value instanceof Variant) {
      return (Literal<T>) new Literals.VariantLiteral((Variant) value);
    }

    throw new IllegalArgumentException(
        String.format(
            "Cannot create expression literal from %s: %s", value.getClass().getName(), value));
  }

  @SuppressWarnings("unchecked")
  static <T> AboveMax<T> aboveMax() {
    return AboveMax.INSTANCE;
  }

  @SuppressWarnings("unchecked")
  static <T> BelowMin<T> belowMin() {
    return BelowMin.INSTANCE;
  }

  private abstract static class BaseLiteral<T> implements Literal<T> {
    private final T value;
    private transient volatile ByteBuffer byteBuffer = null;

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Convert the value to a supported type before calling Literals.from (e.g. java.sql.Date -> LocalDate, Timestamp -> LocalDateTime, BigInteger -> BigDecimal)
  2. Use the typed literal constructors directly (Literals.of, or Expressions.literal with a supported value)
  3. If the type is legitimately needed, extend via string/decimal representation or convert with TypeUtil/DateTimeUtil helpers

Example fix

// before
Literal<?> lit = Literals.from(java.sql.Timestamp.valueOf("2024-01-01 10:00:00")); // IllegalArgumentException
// after
Literal<?> lit = Literals.from(
    java.sql.Timestamp.valueOf("2024-01-01 10:00:00").toLocalDateTime());
Defensive patterns

Strategy: validation

Validate before calling

static boolean supportedLiteralType(Object v) {
  return v instanceof Boolean || v instanceof Integer || v instanceof Long
      || v instanceof Float || v instanceof Double || v instanceof String
      || v instanceof byte[] || v instanceof ByteBuffer || v instanceof UUID
      || v instanceof BigDecimal || v instanceof Variant;
}
// validate before: if (!supportedLiteralType(value)) throw ...

Try / catch

try {
  Literal<?> lit = Literals.from(value);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Cannot create expression literal from")) {
    value = convertToSupportedType(value); // e.g. Timestamp -> LocalDateTime
    return Literals.from(value);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling Literals.from(value) — directly or via Expressions.predicate/expressions built from arbitrary Java objects — with an unsupported type such as a custom POJO, java.util.Date, Instant, OffsetDateTime, LocalDate, or a collection, instead of the expected Iceberg-representable types.

Common situations: Building filter predicates from engine-specific types (Spark TimestampType values as java.sql.Timestamp, java.time types) without converting to Iceberg's expected representations (LocalDate, LocalDateTime, OffsetDateTime handled elsewhere or via proper conversion); passing boxed collection types instead of scalars.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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