hibernate/hibernate-orm · error · QueryException
Can't emulate on error clause on MariaDB
Error message
Can't emulate on error clause on MariaDB
What it means
MariaDB reports json_value path errors as warning 4038 and returns null, so only NULL ON ERROR is emulatable. The MariaDB json_value renderer rejects every other ON ERROR behavior with this QueryException before SQL is generated.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/json/MariaDBJsonValueFunction.java:40
/**
* MariaDB json_value function.
*/
public class MariaDBJsonValueFunction extends JsonValueFunction {
public MariaDBJsonValueFunction(TypeConfiguration typeConfiguration) {
super( typeConfiguration, true, false );
}
@Override
protected void render(
SqlAppender sqlAppender,
JsonValueArguments arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
if ( arguments.errorBehavior() != null && arguments.errorBehavior() != JsonValueErrorBehavior.NULL ) {
// MariaDB reports the error 4038 as warning and simply returns null
throw new QueryException( "Can't emulate on error clause on MariaDB" );
}
if ( arguments.emptyBehavior() != null && arguments.emptyBehavior() != JsonValueEmptyBehavior.NULL ) {
throw new QueryException( "Can't emulate on empty clause on MariaDB" );
}
final JdbcType jdbcType = arguments.returningType() == null
? null
: arguments.returningType().getJdbcMapping().getJdbcType();
if ( jdbcType != null ) {
switch ( jdbcType.getDefaultSqlTypeCode() ) {
case BOOLEAN:
sqlAppender.append( "case " );
break;
case BINARY:
case VARBINARY:
case LONG32VARBINARY:
// We encode binary data as hex, so we have to decode here
sqlAppender.append( "unhex(json_unquote(" );
break;View on GitHub (pinned to fad1729dce)
Solutions
- Remove the ON ERROR clause: plain json_value(doc, path) already returns null on error on MariaDB.
- Use NULL ON ERROR explicitly if you want the behavior documented in the query.
- Implement the DEFAULT fallback with coalesce() around json_value.
- Handle the miss in application code after the query returns null.
Example fix
// before select json_value(e.doc, '$.name' default 'n/a' on error) from Entity e // after select coalesce(json_value(e.doc, '$.name' null on error), 'n/a') from Entity e
Defensive patterns
Strategy: fallback
Validate before calling
boolean mariadb = session.getJdbcServices().getDialect() instanceof org.hibernate.dialect.MariaDBDialect;
if (mariadb && errorBehavior != null && errorBehavior != NULL_ON_ERROR) {
// Plan: drop the clause and wrap with coalesce for the default value.
hql = hql.replace(" default " + defaultExpr + " on error", "");
hql = "select coalesce(" + hql.substring(7), ", " + defaultExpr + ")"; // adjust to your query shape
} Try / catch
try {
return session.createQuery(hql, String.class).getSingleResult();
} catch (org.hibernate.QueryException e) {
if (e.getMessage() != null && e.getMessage().contains("on error clause on MariaDB")) {
// Fallback: NULL ON ERROR plus coalesce for the default value.
return session.createQuery(fallbackHql, String.class).getSingleResult();
}
throw e;
} Prevention
- Do not use DEFAULT ... ON ERROR in shared HQL; use coalesce() around json_value.
- Remember MariaDB always converts json_value errors to null.
- Keep dialect-specific clause usage behind a dialect check.
When it happens
Trigger: An HQL json_value call on MariaDB uses ERROR ON ERROR or DEFAULT <expr> ON ERROR. The check errorBehavior() != null && != JsonValueErrorBehavior.NULL fires.
Common situations: Queries ported from Oracle, where DEFAULT ... ON ERROR is common. Code that wants a fallback value when the path misses.
Related errors
- Can't emulate on empty clause on MariaDB
- Can't emulate on error clause on CockroachDB
- Can't emulate on empty clause on CockroachDB
- CockroachDB json_value only support literal json paths, but
- Can't emulate on error clause on H2
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/a2c44f80e57c8ff5.
Report an issue: GitHub.