hibernate/hibernate-orm · error · QueryException

Can't emulate error on empty clause on H2

Error message

Can't emulate error on empty clause on H2

What it means

For json_query() on H2, ERROR ON EMPTY has no emulation: the dereference-based rendering naturally yields NULL for a missing path, and raising an error instead cannot be expressed in the emulation. The translator accepts NULL (the default) and the empty-array/empty-object variants, but throws when emptyBehavior() == JsonQueryEmptyBehavior.ERROR.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/json/H2JsonQueryFunction.java:39

 */
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,
			Expression jsonDocument,
			boolean isJsonType,
			Expression jsonPathExpression,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove error on empty and let the default NULL ON EMPTY apply
  2. Detect emptiness in application code by checking for a null result instead of asking the database to raise
  3. Run these queries against the production database in tests (Testcontainers)
  4. Use a native query if ERROR ON EMPTY semantics are mandatory

Example fix

// before - throws on H2
select json_query(d.doc, '$.tags[*]' error on empty) from Document d

// after - default NULL ON EMPTY; check for null in Java
select json_query(d.doc, '$.tags[*]') from Document d
Defensive patterns

Strategy: validation

Validate before calling

// Reject ERROR ON EMPTY for json_query on H2 before execution
static void assertTranslatable(SessionFactory sf, String hql) {
    if (sf.getJdbcServices().getDialect() instanceof org.hibernate.dialect.H2Dialect
            && hql.toLowerCase().contains("error on empty")) {
        throw new IllegalArgumentException(
            "H2 json_query cannot emulate 'error on empty'; rely on the default NULL ON EMPTY");
    }
}

Try / catch

try {
    return session.createQuery(hql, String.class).getSingleResult();
} catch (org.hibernate.QueryException e) {
    if (e.getMessage() != null && e.getMessage().contains("error on empty clause on H2")) {
        // Retry with default NULL ON EMPTY and treat null as 'missing'
        return session.createQuery(stripClause(hql, "error on empty"), String.class).getSingleResult();
    }
    throw e;
}

Prevention

When it happens

Trigger: HQL on the H2 dialect: select json_query(d.doc, '$.tags[*]' error on empty) from Document d. Only this strict form is rejected; null on empty and empty array/object on empty pass through.

Common situations: Strict-mode queries ported from Oracle or SQL Server where ERROR ON EMPTY is explicit; H2 unit tests starting to fail after a strictness clause was added for production semantics.

Related errors


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