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

  1. Ensure translation happens with parameter bindings available — bind all query parameters before executing/rendering
  2. Avoid parameter markers in positions the dialect must inline as literals (e.g. literal limit/offset constants or literal function arguments)
  3. In custom translator code, only call getLiteralValue()/interpretExpression() during the bound translation phase, and guard for null bindings
  4. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/955b46c1c35dcee9. Report an issue: GitHub.