hibernate/hibernate-orm · error · IllegalArgumentException
Can't interpret expression because no parameter bindings are
Error message
Can't interpret expression because no parameter bindings are available
What it means
AbstractSqlAstTranslator.interpretExpression() must turn an expression into a concrete Java value; for JdbcParameter nodes it reads the current JdbcParameterBindings. When it is invoked while jdbcParameterBindings is null — typically via getLiteralValue() from places that need real values (dialects inlining limit/offset or function arguments like concat as literals, or integrator subclasses calling it outside the bound translation phase) — it throws IllegalArgumentException: the value simply cannot be known without bindings.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java:653
}
protected void setLimitParameter(JdbcParameter limitParameter) {
this.limitParameter = limitParameter;
}
@Override
public <X> X getLiteralValue(Expression expression) {
return interpretExpression( expression, jdbcParameterBindings );
}
@SuppressWarnings("unchecked")
protected <R> R interpretExpression(Expression expression, JdbcParameterBindings jdbcParameterBindings) {
if ( expression instanceof Literal literal ) {
return (R) literal.getLiteralValue();
}
else if ( expression instanceof JdbcParameter jdbcParameter ) {
if ( jdbcParameterBindings == null ) {
throw new IllegalArgumentException( "Can't interpret expression because no parameter bindings are available" );
}
return (R) getParameterBindValue( jdbcParameter );
}
else if ( expression instanceof SqmParameterInterpretation parameterInterpretation ) {
if ( jdbcParameterBindings == null ) {
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;
}View on GitHub (pinned to fad1729dce)
Solutions
- Ensure translation happens with parameter bindings available — bind all query parameters before executing/rendering
- Avoid parameter markers in positions the dialect must inline as literals (e.g. literal limit/offset constants or literal function arguments)
- In custom translator code, only call getLiteralValue()/interpretExpression() during the bound translation phase, and guard for null bindings
- Upgrade Hibernate — inlining decisions around parameters change between 6.x minor releases
Example fix
// before (HQL)
em.createQuery("select o from Order o order by o.id")
.setFirstResult(offsetParam).setMaxResults(limitParam); // params reach literal-requiring path
// after
em.createQuery("select o from Order o order by o.id")
.setFirstResult(200).setMaxResults(50); // concrete values inline cleanly Defensive patterns
Strategy: validation
Validate before calling
// integrator-side: only interpret expressions when bindings exist
JdbcParameterBindings bindings = getJdbcParameterBindings();
if (bindings == null) {
throw new IllegalStateException("bind parameters before interpreting expressions");
}
return getLiteralValue(expression); Type guard
boolean isInterpretable(Expression expr, JdbcParameterBindings bindings) {
return expr instanceof Literal || (isParameterLike(expr) && bindings != null);
} Try / catch
try {
return getLiteralValue(expression);
}
catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("no parameter bindings")) {
// fall back: render as a JDBC parameter marker instead of a literal
renderAsParameterMarker(expression);
}
else throw e;
} Prevention
- Bind all query parameters before execution; never render/translate SQL before binding
- Use literal constants where a dialect must inline values (limits, folded function args)
- In custom translator code, check for null bindings before calling getLiteralValue()
When it happens
Trigger: A SQL AST parameter reaching a translation path that must interpret it as a literal while no JdbcParameterBindings were supplied: parameterized limit/offset on dialects requiring literal values, arguments of functions the translator folds locally, or a custom translator/dialect hook calling getLiteralValue() before bindings exist.
Common situations: Third-party dialects or translator customizations; native-image or query-rewriting integrations that render SQL before parameter binding; framework code caching Translator output (SQL strings) at a point where parameters are not yet bound.
Related errors
- Expected table group with table joins to have an entity type
- Could not configure c3p0: " + e.getMessage()
- JDBC Driver class " + jdbcDriverClass + " not found
- Summarization is not supported by DBMS!
- unsupported temporal unit for CUBRID: " + unit
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/955b46c1c35dcee9.
Report an issue: GitHub.