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

  1. Inline the path as a string literal: json_value(d.doc, '$.items[0].name')
  2. Keep the path literal and parameterize only varying parts inside it via PASSING: json_value(d.doc, '$.items[$i]' passing :idx as i)
  3. Maintain a bounded whitelist of literal-path queries instead of one parameterized query
  4. 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

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


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