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
- 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
- toByteBuffer is not supported
- AboveMax has no value
- Cannot change the type of AboveMax
- Counter for type %s is not supported
- Counter for type %s is not supported
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/ec89562be09b9145.
Report an issue: GitHub.