hibernate/hibernate-orm · error · QueryException
Can't emulate on error clause on H2
Error message
Can't emulate on error clause on H2
What it means
H2 has no native json_query(); Hibernate emulates it with dereference expressions, which error out on invalid JSON documents by nature. Consequently only the default ERROR ON ERROR behavior is emulatable - requesting null on error (or an empty-array/empty-object on-error form) is rejected during SQL rendering.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/json/H2JsonQueryFunction.java:36
/**
* H2 json_query function.
*/
public class H2JsonQueryFunction extends JsonQueryFunction {
public H2JsonQueryFunction(TypeConfiguration typeConfiguration) {
super( typeConfiguration, false, true );
}
@Override
protected void render(
SqlAppender sqlAppender,
JsonQueryArguments arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
// Json dereference errors by default if the JSON is invalid
if ( arguments.errorBehavior() != null && arguments.errorBehavior() != JsonQueryErrorBehavior.ERROR ) {
throw new QueryException( "Can't emulate on error clause on H2" );
}
if ( arguments.emptyBehavior() == JsonQueryEmptyBehavior.ERROR ) {
throw new QueryException( "Can't emulate error on empty clause on H2" );
}
appendJsonQuery(
sqlAppender,
arguments.jsonDocument(),
arguments.isJsonType(),
arguments.jsonPath(),
arguments.passingClause(),
arguments.wrapMode(),
arguments.emptyBehavior(),
walker
);
}
static void appendJsonQuery(
SqlAppender sqlAppender,View on GitHub (pinned to fad1729dce)
Solutions
- Omit the on error clause - the default ERROR behavior is what the emulation implements
- Ensure documents are valid before querying (write-time validation or where d.doc is json)
- Run these queries in tests against a production-like database via Testcontainers
- Use a native query when lenient error handling is a hard requirement
Example fix
// before - throws on H2 select json_query(d.doc, '$.tags[*]' null on error) from Document d // after - default ERROR ON ERROR; ensure documents are valid select json_query(d.doc, '$.tags[*]') from Document d
Defensive patterns
Strategy: validation
Validate before calling
// Reject non-default ON ERROR clauses for json_query on H2 before execution
static void assertTranslatable(SessionFactory sf, String hql) {
if (sf.getJdbcServices().getDialect() instanceof org.hibernate.dialect.H2Dialect) {
String h = hql.toLowerCase();
if (h.contains("json_query")) {
int i = h.indexOf("on error");
if (i >= 0 && !h.startsWith("error on error", i)) {
throw new IllegalArgumentException(
"H2 json_query only supports the default 'error on error'; remove the clause");
}
}
}
} Try / catch
try {
return session.createQuery(hql, String.class).getResultList();
} catch (org.hibernate.QueryException e) {
if (e.getMessage() != null && e.getMessage().contains("on error clause on H2")) {
return session.createQuery(stripClause(hql, "on error"), String.class).getResultList();
}
throw e;
} Prevention
- Omit ON ERROR clauses in portable HQL; they are the least portable part of the SQL/JSON grammar
- Validate documents at write time so the default ERROR behavior never triggers
- Run JSON-heavy tests against the production dialect via Testcontainers, not only H2
When it happens
Trigger: HQL on the H2 dialect: select json_query(d.doc, '$.tags[*]' null on error) from Document d. The check arguments.errorBehavior() != JsonQueryErrorBehavior.ERROR in H2JsonQueryFunction.render() throws for any non-default error behavior.
Common situations: Queries written with Oracle/SQL Server habits where NULL ON ERROR is the defensive default, then executed in H2-based unit tests; adopting Hibernate 6.6+/7.x JSON functions with H2 as the development database.
Related errors
- Can't emulate error on empty clause on H2
- Can't emulate null on error clause on H2
- Can't emulate on error clause on H2
- Can't emulate error on empty clause on H2
- Can't emulate on error clause on SingleStore
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/641f385ef90892e1.
Report an issue: GitHub.