hibernate/hibernate-orm · error · UnsupportedOperationException
Can't interpret expression:
Error message
Can't interpret expression:
What it means
Thrown from AbstractSqlAstTranslator.interpretExpression while SQL is being generated, when a dialect emulation needs the concrete Java value of an expression (constant folding). The interpreter only handles Literal, bound JdbcParameter / SqmParameterInterpretation, and exactly one function, 'concat'; every other node type (arithmetic, CASE, most function calls, subqueries) falls through to 'throw new UnsupportedOperationException("Can't interpret expression: " + expression)'. The message appends the expression's toString(), which tells you which node could not be folded.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java:677
throw new IllegalArgumentException( "Can't interpret expression because no parameter bindings are available" );
}
return (R) getParameterBindValue( (JdbcParameter) parameterInterpretation.getResolvedExpression() );
}
else if ( expression instanceof FunctionExpression functionExpression ) {
if ( "concat".equals( functionExpression.getFunctionName() ) ) {
final List<? extends SqlAstNode> arguments = functionExpression.getArguments();
final StringBuilder sb = new StringBuilder();
for ( SqlAstNode argument : arguments ) {
final Object argumentLiteral = interpretExpression( (Expression) argument, jdbcParameterBindings );
if ( argumentLiteral == null ) {
return null;
}
sb.append( argumentLiteral );
}
return (R) sb.toString();
}
}
throw new UnsupportedOperationException( "Can't interpret expression: " + expression );
}
protected void renderExpressionAsLiteral(Expression expression, JdbcParameterBindings jdbcParameterBindings) {
if ( expression instanceof Literal ) {
expression.accept( this );
return;
}
else if ( expression instanceof JdbcParameter parameter ) {
if ( jdbcParameterBindings == null ) {
throw new IllegalArgumentException( "Can't interpret expression because no parameter bindings are available" );
}
renderAsLiteral( parameter, getParameterBindValue( parameter ) );
return;
}
else if ( expression instanceof SqmParameterInterpretation parameterInterpretation ) {
if ( jdbcParameterBindings == null ) {
throw new IllegalArgumentException( "Can't interpret expression because no parameter bindings are available" );
}View on GitHub (pinned to fad1729dce)
Solutions
- Rewrite the HQL/JPQL so the offending position holds a literal or plain column instead of a function/CASE/arithmetic expression (compute the value in Java and bind it as a parameter that the emulation can resolve).
- Move the expression out of the emulated fragment (e.g., out of the ORDER BY / FETCH / emulated predicate) so no interpretation is needed.
- Run the statement as a native SQL query (createNativeQuery) where the dialect emulation path is bypassed.
- Upgrade hibernate-core — the set of foldable expressions and which dialects need folding changes between minor versions.
- If you maintain a custom dialect, override interpretExpression in your SqlAstTranslator subclass to handle the node type.
Example fix
// before — dialect emulation must interpret the CASE expression and fails
List<Employee> es = session.createQuery(
"select e from Employee e order by case when e.alias is null then e.name else e.alias end",
Employee.class).list();
// after — do the folding in Java and bind the result so only literals/parameters remain
List<Employee> es = session.createQuery(
"select e from Employee e where e.name = :effectiveName",
Employee.class).setParameter("effectiveName", effective).list(); Defensive patterns
Strategy: try-catch
Try / catch
try {
List<Employee> rows = query.list();
} catch (org.hibernate.query.IllegalQueryOperationException | UnsupportedOperationException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Can't interpret expression")) {
// dialect cannot constant-fold this expression: fall back to native SQL or simplify the query
log.warn("Unsupported expression for dialect emulation: {}", e.getMessage());
rows = runNativeFallback();
} else { throw e; }
} Prevention
- Keep emulated positions (limit clauses, emulated functions) free of CASE/arithmetic/non-concat function expressions; prefer literals or bound parameters.
- Test queries against the production dialect, not just H2, in CI.
- Pin hibernate-core versions and read migration notes before upgrading — emulation coverage changes between minors.
When it happens
Trigger: Executing a query on a dialect whose translator must inline real values during rendering (limit/offset inlining, function or predicate emulations that call getLiteralValue()/interpretExpression), where the expression in that position is anything other than a literal, a bound parameter, or a concat() tree — e.g. coalesce()/substring()/CASE/arithmetic inside the emulated fragment.
Common situations: Combining pagination or dialect-specific emulations with expressions the translator cannot fold; upgrading hibernate-core and hitting a newly active emulation path; custom dialects overriding interpretExpression; HQL that works on PostgreSQL but fails on H2/SQL Server/Oracle because only the latter's translator needs the value.
Related errors
- Can't render expression as literal:
- removeTableGroupJoin not supported by %s
- Injection of parent instance into embeddable result is not p
- The Embeddable: %s parent initializer is neither an instance
- dynamic instantiation in a sub-query is unsupported
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/4c81f73471b84cc9.
Report an issue: GitHub.