hibernate/hibernate-orm · error · QueryException
H2 json_table() passing clause only supports literal json pa
Error message
H2 json_table() passing clause only supports literal json path passing values, but got {expression} What it means
For json_table() on H2, the emulation inlines passing values directly into the rebuilt path text, so every passing expression must be a Literal. If the expression bound in the PASSING clause is a bind parameter or any computed expression, this QueryException reports the unsupported expression.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/json/H2JsonValueFunction.java:193
sb.append( " format json" );
}
sb.append( ')' );
}
for ( int i = 0; i < jsonPathElements.size(); i++ ) {
final JsonPathHelper.JsonPathElement jsonPathElement = jsonPathElements.get( i );
if ( jsonPathElement instanceof JsonPathHelper.JsonAttribute attribute ) {
sb.append( "." );
QuotingHelper.appendDoubleQuoteEscapedString( sb, attribute.attribute() );
}
else if ( jsonPathElement instanceof JsonPathHelper.JsonParameterIndexAccess parameterIndexAccess ) {
assert passingClause != null;
final String parameterName = parameterIndexAccess.parameterName();
final Expression expression = passingClause.getPassingExpressions().get( parameterName );
if ( expression == null ) {
throw new QueryException( "JSON path [" + jsonPath + "] uses parameter [" + parameterName + "] that is not passed" );
}
if ( !( expression instanceof Literal literal) ) {
throw new QueryException( "H2 json_table() passing clause only supports literal json path passing values, but got " + expression );
}
sb.append( '[' );
sb.append( literal.getLiteralValue() );
sb.append( "+1]" );
}
else {
sb.append( '[' );
sb.append( ( (JsonPathHelper.JsonIndexAccess) jsonPathElement ).index() + 1 );
sb.append( ']' );
}
}
return sb.toString();
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Replace the bind parameter with a literal value in the PASSING clause, for example PASSING 3 AS i.
- Build the HQL with the literal value interpolated so the passing expression stays a literal node.
- Switch this statement to a native query when the value must stay a bind parameter.
- Test such statements on a dialect with native json_table support.
Example fix
// before
Query q = session.createQuery(
"select t.name from Entity e, json_table(e.doc, '$.rows[$i]' passing :n as i columns(name varchar)) t");
q.setParameter("n", 2);
// after
Query q = session.createQuery(
"select t.name from Entity e, json_table(e.doc, '$.rows[$i]' passing 2 as i columns(name varchar)) t"); Defensive patterns
Strategy: validation
Validate before calling
// H2 json_table emulation: passing values must be literals.
boolean isH2 = session.getJdbcServices().getDialect() instanceof org.hibernate.dialect.H2Dialect;
if (isH2 && usesBindParameterInPassing) {
throw new IllegalStateException("H2 json_table PASSING requires literal values; interpolate the value into HQL");
}
String hql = "select t.name from Entity e, json_table(e.doc, '$.rows[$i]' passing " + n + " as i columns(name varchar)) t"; Try / catch
try {
return session.createQuery(hql).getResultList();
} catch (org.hibernate.QueryException e) {
if (e.getMessage() != null && e.getMessage().contains("literal json path passing values")) {
throw new UnsupportedOperationException("Interpolate a literal value into the H2 json_table PASSING clause", e);
}
throw e;
} Prevention
- Treat H2 json_table as a test-only convenience; keep production paths on native dialects.
- When tests run on H2, generate HQL with interpolated literals instead of bind parameters for passing values.
When it happens
Trigger: A json_table() query on H2 passes a query parameter, for example PASSING :offset AS i. The instanceof Literal check fails because the expression is a junction or parameter node, and rendering aborts.
Common situations: Developers bind the index as a JDBC parameter to allow plan caching, which H2 emulation cannot inline. Queries written for Oracle or PostgreSQL json_table run unchanged on H2 test databases.
Related errors
- H2 json_table() only supports literal json paths, but got "
- Can't emulate null on error clause on H2
- H2 json_table() only supports literal json paths, but got {j
- H2 json_table() only supports literal default expressions, b
- H2 json_value only support literal json paths, but got {json
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/c00f6e4a2da18d2d.
Report an issue: GitHub.