hibernate/hibernate-orm · error · QueryException
H2 json_table() only supports literal json paths, but got {j
Error message
H2 json_table() only supports literal json paths, but got {jsonPath} What it means
Beyond the initial transformation, the H2 json_table() emulation also computes the parent read path for columns while building the lateral subquery select. That step again needs the literal path text (to detect array access and to strip a trailing [*]), so a non-literal path expression makes this code path throw during SQL generation, even if earlier checks passed.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/json/H2JsonTableFunction.java:620
boolean lateral,
boolean withOrdinality,
SqmToSqlAstConverter converter) {
final JsonTableArguments arguments = JsonTableArguments.extract( sqlAstNodes );
final Expression jsonDocument = arguments.jsonDocument();
final String documentPath;
final ColumnReference columnReference = jsonDocument.getColumnReference();
if ( columnReference != null ) {
documentPath = columnReference.getExpressionText();
}
else {
documentPath = tableIdentifierVariable + "_." + "d";
}
final String parentPath;
final boolean isArray;
if ( arguments.jsonPath() != null ) {
if ( !( arguments.jsonPath() instanceof Literal literal) ) {
throw new QueryException( "H2 json_table() only supports literal json paths, but got " + arguments.jsonPath() );
}
final String rawJsonPath = (String) literal.getLiteralValue();
isArray = isArrayAccess( rawJsonPath );
final String jsonPath = isArray ? rawJsonPath.substring( 0, rawJsonPath.length() - 3 ) : rawJsonPath;
parentPath = H2JsonValueFunction.applyJsonPath( documentPath, true, arguments.isJsonType(), jsonPath, arguments.passingClause() );
}
else {
// We have to assume this is an array
isArray = true;
parentPath = documentPath;
}
final String parentReadExpression;
if ( isArray ) {
parentReadExpression = parentPath + "[" + tableIdentifierVariable + ".x]";
}
else {
parentReadExpression = '(' + parentPath + ')';View on GitHub (pinned to fad1729dce)
Solutions
- Inline the literal path: json_table(d.doc, '$.items[*]' columns(...))
- Parameterize inner parts with PASSING while keeping the path string literal
- Use a native H2 query for dynamic paths
- Guard with a repository-layer check that json_table paths are string literals
Example fix
// before - throws on H2 select t.name from Document d, json_table(d.doc, :path columns(name varchar)) t // after - literal path select t.name from Document d, json_table(d.doc, '$.items[*]' columns(name varchar)) t
Defensive patterns
Strategy: validation
Validate before calling
// Heuristic lint: json_table paths must be string literals on H2
private static final Pattern PARAM_TABLE_PATH =
Pattern.compile("(?i)json_table\\s*\\([^,]+,\\s*:\\w+");
static void assertLiteralJsonPaths(String hql) {
if (PARAM_TABLE_PATH.matcher(hql).find()) {
throw new IllegalArgumentException(
"json_table path must be a string literal on H2; column read paths are derived from the path text");
}
} Type guard
// Java predicate (type-guard analogue) for Criteria/SQM path expressions
static boolean isLiteralPath(org.hibernate.query.sqm.tree.expression.SqmExpression<?> pathExpr) {
return pathExpr instanceof org.hibernate.query.sqm.tree.expression.SqmLiteral<?>;
} Try / catch
try {
return session.createQuery(hql, Object[].class).getResultList();
} catch (org.hibernate.QueryException e) {
if (e.getMessage() != null && e.getMessage().contains("only supports literal json paths")) {
throw new IllegalArgumentException("Inline the json_table path as a literal: " + hql, e);
}
throw e;
} Prevention
- Treat the json_table path as part of the query text, not a runtime value, on H2
- Cover every json_table query in a per-dialect integration test
- Refactor dynamic paths into a small set of literal-path query templates
When it happens
Trigger: An H2 json_table() call with a non-literal path expression that reaches the nested transformer - typically the same query that binds the path: json_table(d.doc, :path columns(...)), or a path slot filled with a dynamic expression.
Common situations: Parameterized json_table queries in generic flattening code; refactors that moved a formerly literal path into a bind parameter without updating the H2 tests.
Related errors
- H2 json_table() only supports literal json paths, but got "
- H2 json_value only support literal json paths, but got " + a
- H2 json_query only support literal json paths, but got " + j
- H2 json_table() only supports literal default expressions, b
- CockroachDB json_value only support literal json paths, but
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/0ff1e98d1611ede0.
Report an issue: GitHub.