hibernate/hibernate-orm · error · QueryException
CockroachDB json_value only support literal json paths, but
Error message
CockroachDB json_value only support literal json paths, but got " + arguments.jsonPath()
What it means
The CockroachDB json_value() emulation cannot pass the JSON path through to the database: it parses the path string (JsonPathHelper.parseJsonPathElements) and re-renders it as jsonb path constructor elements with dialect-quoted literals. That rewrite is only possible when the path is a compile-time string literal; walker.getLiteralValue() fails for bind parameters and computed expressions, and Hibernate rethrows as this QueryException during SQL rendering.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/json/CockroachDBJsonValueFunction.java:50
@Override
protected void render(
SqlAppender sqlAppender,
JsonValueArguments arguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
// jsonb_path_query_first errors by default
if ( arguments.errorBehavior() != null && arguments.errorBehavior() != JsonValueErrorBehavior.ERROR ) {
throw new QueryException( "Can't emulate on error clause on CockroachDB" );
}
if ( arguments.emptyBehavior() != null && arguments.emptyBehavior() != JsonValueEmptyBehavior.NULL ) {
throw new QueryException( "Can't emulate on empty clause on CockroachDB" );
}
final String jsonPath;
try {
jsonPath = walker.getLiteralValue( arguments.jsonPath() );
}
catch (Exception ex) {
throw new QueryException( "CockroachDB json_value only support literal json paths, but got " + arguments.jsonPath() );
}
appendJsonValue(
sqlAppender,
arguments.jsonDocument(),
JsonPathHelper.parseJsonPathElements( jsonPath ),
arguments.isJsonType(),
arguments.passingClause(),
arguments.returningType(),
walker
);
}
private static boolean isBinary(@Nullable CastTarget castTarget) {
return castTarget != null && castTarget.getJdbcMapping().getJdbcType().isBinary();
}
static void appendJsonValue(SqlAppender sqlAppender, Expression jsonDocument, List<JsonPathHelper.JsonPathElement> jsonPathElements, boolean isJsonType, JsonPathPassingClause jsonPathPassingClause, CastTarget castTarget, SqlAstTranslator<?> walker) {
final boolean isBinary = isBinary( castTarget );View on GitHub (pinned to fad1729dce)
Solutions
- Inline the path as a string literal: json_value(d.doc, '$.items[0].name')
- Keep the path literal and parameterize only varying parts inside it via PASSING: json_value(d.doc, '$.items[$i]' passing :idx as i)
- Maintain a bounded whitelist of literal-path queries instead of one parameterized query
- Fall back to a native SQL query using jsonb_path_query_first() for fully dynamic paths
Example fix
// before - path bound as a query parameter, throws on CockroachDB select json_value(d.doc, :path) from Document d // after - literal path; parameterize sub-parts with the passing clause select json_value(d.doc, '$.items[$i]' passing :idx as i) from Document d
Defensive patterns
Strategy: validation
Validate before calling
// Heuristic lint: json_* paths must be string literals, not bind parameters
private static final Pattern PARAM_JSON_PATH =
Pattern.compile("(?i)json_(value|exists|query|table)\\s*\\([^,]+,\\s*:\\w+");
static void assertLiteralJsonPaths(String hql) {
if (PARAM_JSON_PATH.matcher(hql).find()) {
throw new IllegalArgumentException(
"JSON path must be a string literal on CockroachDB/H2; use PASSING for variable parts");
}
} 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, String.class).getResultList();
} catch (org.hibernate.QueryException e) {
if (e.getMessage() != null && e.getMessage().contains("only support literal json paths")) {
throw new IllegalArgumentException(
"JSON path must be a literal on this dialect; got: " + hql, e);
}
throw e;
} Prevention
- Write JSON paths as string literals in HQL; parameterize varying indexes/attributes with the PASSING clause
- Never route user-supplied JSON paths into json_* bind parameters on H2/CockroachDB
- Add one repository-layer test per dialect that executes every json_* query your code ships
When it happens
Trigger: json_value() on the CockroachDB dialect whose second argument is not a string literal, e.g. select json_value(d.doc, :path) from Document d, or a path built with string concatenation or a function call. Note that PASSING does not help here - the path argument itself must be a literal.
Common situations: Reusable repository methods that store the JSON path in a variable or receive it from the UI; code migrated from the PostgreSQL dialect where a parameterized path worked; report generators that build paths dynamically.
Related errors
- JSON path [" + JsonPathHelper.toJsonPath( jsonPathElements )
- Can't emulate on error clause on CockroachDB
- Can't emulate on empty clause on CockroachDB
- H2 json_value only support literal json paths, but got " + a
- H2 json_query only support literal json paths, but got " + j
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/cff3aa6bb6e91ef5.
Report an issue: GitHub.