quarkusio/quarkus · error · IllegalStateException
Expression is not a literal:
Error message
Expression is not a literal:
What it means
asLiteral() returns the pre-evaluated literal value of a literal expression as a CompletionStage. It throws IllegalStateException when the ExpressionImpl was not constructed as a literal (literal field is null), meaning the expression is dynamic or a part-based expression that has no cached literal value.
Source
Thrown at independent-projects/qute/core/src/main/java/io/quarkus/qute/ExpressionImpl.java:95
@Override
public boolean isLiteral() {
return literal != null && parts.size() <= 1;
}
public CompletableFuture<Object> getLiteralValue() {
return literal != null ? literal.toCompletableFuture() : null;
}
@Override
public Object getLiteral() {
return literal != null ? literal.get() : null;
}
@Override
public CompletionStage<Object> asLiteral() {
if (literal == null) {
throw new IllegalStateException("Expression is not a literal: " + toString());
}
return literal;
}
public Origin getOrigin() {
return origin;
}
@Override
public int getGeneratedId() {
return id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Objects.hashCode(toOriginalString());View on GitHub (pinned to e1c734241f)
Solutions
- Guard with expression.isLiteral() (or check the literal field) before calling asLiteral().
- Fall back to evaluating the expression through the resolution context when it is not a literal.
- Inspect the template expression origin to confirm it was created as a literal.
Example fix
// before
Object v = expr.asLiteral().toCompletableFuture().join();
// after
if (expr.isLiteral()) {
Object v = expr.asLiteral().toCompletableFuture().join();
} else {
Object v = expr.eval(resolutionContext).toCompletableFuture().join();
} Defensive patterns
Strategy: type-guard
Validate before calling
if (expr == null || !expr.isLiteral()) {
// not usable as literal — evaluate dynamically instead
} Type guard
boolean isLiteralExpr(Expression e) {
return e instanceof ExpressionImpl impl && impl.isLiteral();
} Try / catch
try {
return expr.asLiteral().toCompletableFuture().join();
} catch (IllegalStateException ex) {
return expr.eval(ctx).toCompletableFuture().join(); // dynamic fallback
} Prevention
- Only call asLiteral() on expressions you created via literal()/literalFrom()
- Check isLiteral() before treating an expression as constant
- Prefer full evaluation for user-authored template expressions
When it happens
Trigger: Calling asLiteral() on an expression created via parts (e.g. from a normal template expression like {name}) rather than via literal()/literalFrom().
Common situations: Extension or custom resolver code that assumes an expression is a constant and calls asLiteral() on user-supplied template expressions that turn out to be dynamic (contain method calls, properties, etc.).
Related errors
- Object param not present
- Invalid template link [${templateLink}] - Expeting a link th
- No template variant found
- Templates that are not backed by a file must provide extensi
- Tracing not enabled
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/fcc2fe63d4d81260.
Report an issue: GitHub.