hibernate/hibernate-orm · error · QueryException
H2 json_value only support literal json paths, but got {json
Error message
H2 json_value only support literal json paths, but got {jsonPath} What it means
Hibernate emulates json_value() on H2 by building a regexp_replace() expression at SQL generation time. To do this, it must read the JSON path as a string literal through SqlAstTranslator.getLiteralValue(). When the path argument is a bind parameter or any non-literal expression, getLiteralValue throws, and this QueryException reports it. The error occurs during query translation, before SQL runs against H2.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/json/H2JsonValueFunction.java:73
}
final boolean hexDecoding;
if ( arguments.returningType() != null ) {
hexDecoding = H2JsonValueFunction.needsHexDecoding( arguments.returningType().getJdbcMapping() );
sqlAppender.appendSql( "cast(" );
if ( hexDecoding ) {
// We encode binary data as hex, so we have to decode here
sqlAppender.appendSql( "hextoraw(regexp_replace(" );
}
}
else {
hexDecoding = false;
}
final String jsonPath;
try {
jsonPath = walker.getLiteralValue( arguments.jsonPath() );
}
catch (Exception ex) {
throw new QueryException( "H2 json_value only support literal json paths, but got " + arguments.jsonPath() );
}
sqlAppender.appendSql( "stringdecode(regexp_replace(nullif(" );
renderJsonPath(
sqlAppender,
arguments.jsonDocument(),
arguments.isJsonType(),
walker,
jsonPath,
arguments.passingClause()
);
sqlAppender.appendSql( ",JSON'null'),'^\"(.*)\"$','$1'))");
if ( arguments.returningType() != null ) {
if ( hexDecoding ) {
sqlAppender.appendSql( ",'([0-9a-f][0-9a-f])','00$1'))" );
}
sqlAppender.appendSql( " as " );View on GitHub (pinned to fad1729dce)
Solutions
- Inline the JSON path as a string literal: json_value(e.doc, '$.name') instead of json_value(e.doc, :path).
- Build the HQL string in Java by concatenating the path constant, so each generated query still contains a literal path.
- If the path must be dynamic per execution, fall back to a native query for this statement.
- Run the test against a dialect with native JSON support (PostgreSQL, Oracle, SQL Server) when the query uses dynamic paths.
Example fix
// before
List results = session.createQuery("select json_value(e.doc, :p) from Entity e", String.class)
.setParameter("p", "$.customer.name")
.getResultList();
// after
List results = session.createQuery("select json_value(e.doc, '$.customer.name') from Entity e", String.class)
.getResultList(); Defensive patterns
Strategy: validation
Validate before calling
// Before creating the query: only H2 needs a literal path.
boolean isH2 = session.getJdbcServices().getDialect() instanceof org.hibernate.dialect.H2Dialect;
String path = "$" + ".customer.name";
if (isH2 && pathIsParameter) {
throw new IllegalStateException("H2 json_value requires a literal JSON path: " + path);
}
// Build HQL with the path inlined as a literal.
String hql = "select json_value(e.doc, '" + path + "') from Entity e"; Try / catch
try {
return session.createQuery(hql, String.class).getResultList();
} catch (org.hibernate.QueryException e) {
if (e.getMessage() != null && e.getMessage().contains("literal json paths")) {
throw new UnsupportedOperationException("Inline the JSON path as a literal for H2", e);
}
throw e;
} Prevention
- Keep a project rule: JSON path arguments are string literals, never query parameters.
- Store path constants next to the query strings that use them.
- Run JSON query integration tests on the production dialect, not only on H2.
When it happens
Trigger: An HQL or Criteria query calls json_value(doc, :path) or json_value(doc, someExpression) while the H2Dialect is active. The path is not a quoted string literal, so walker.getLiteralValue(arguments.jsonPath()) fails and the catch block throws.
Common situations: Developers write a query once for PostgreSQL or Oracle (native json_value accepts parameters) and run integration tests on H2. Or they try to keep the path configurable through a query parameter. H2 test containers and in-memory H2 databases expose the limitation.
Related errors
- Can't emulate on error clause on H2
- Can't emulate error on empty clause on H2
- Can't emulate on error clause on CockroachDB
- Can't emulate on empty clause on CockroachDB
- Can't emulate on error clause on H2
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/068ab68094d39a1a.
Report an issue: GitHub.