apache/iceberg · error · IllegalArgumentException
Cannot create expression literal from
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.
Solutions
- Convert the value to a supported type before calling Literals.from (e.g. java.sql.Date -> LocalDate, Timestamp -> LocalDateTime, BigInteger -> BigDecimal)
- Use the typed literal constructors directly (Literals.of, or Expressions.literal with a supported value)
- 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
- Convert engine-specific date/time types to java.time types Iceberg supports before building literals
- Never pass POJOs, collections, or java.util.Date/java.sql.* directly to Literals.from
- Check the value's class against Literals' supported types when building filters from dynamic input
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
- AboveMax has no value
- Cannot change the type of AboveMax
- Cannot convert dict encoded field
- Cannot parse type string: variant is not a primitive type
- Counter for type is not supported
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/ec89562be09b9145.
Report an issue: GitHub.
Appendix: 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)