hibernate/hibernate-orm · error · QueryException

SingleStore json_query only support literal json paths, but

Error message

SingleStore json_query only support literal json paths, but got " + arguments.jsonPath() + "

What it means

SingleStoreJsonQueryFunction decomposes the SQL/JSON path into individual json_extract_string(doc, 'attr', 'attr2') arguments at SQL-render time, so the path string must be known when the query is translated. It calls walker.getLiteralValue(arguments.jsonPath()) to read it; if the second argument is a bind parameter/parameter marker rather than a string literal, that call throws and the dialect rethrows this QueryException.

Source

Thrown at hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/function/json/SingleStoreJsonQueryFunction.java:47

	@Override
	protected void render(
			SqlAppender sqlAppender,
			JsonQueryArguments arguments,
			ReturnableType<?> returnType,
			SqlAstTranslator<?> walker) {
		if ( arguments.errorBehavior() != null && arguments.errorBehavior() != JsonQueryErrorBehavior.ERROR ) {
			throw new QueryException( "Can't emulate on error clause on SingleStore" );
		}
		if ( arguments.emptyBehavior() != null && arguments.emptyBehavior() != JsonQueryEmptyBehavior.NULL ) {
			throw new QueryException( "Can't emulate on empty clause on SingleStore" );
		}
		else {
			final String jsonPath;
			try {
				jsonPath = walker.getLiteralValue( arguments.jsonPath() );
			}
			catch (Exception ex) {
				throw new QueryException( "SingleStore json_query only support literal json paths, but got " + arguments.jsonPath() );
			}
			final List<JsonPathHelper.JsonPathElement> jsonPathElements = JsonPathHelper.parseJsonPathElements( jsonPath );
			final JsonQueryWrapMode wrapMode = arguments.wrapMode();
			final DecorationMode decorationMode = determineDecorationMode( wrapMode );
			if ( decorationMode == DecorationMode.WRAP ) {
				sqlAppender.appendSql( "concat('['," );
			}
			sqlAppender.appendSql( "nullif(json_extract_string(" );
			arguments.jsonDocument().accept( walker );
			for ( JsonPathHelper.JsonPathElement pathElement : jsonPathElements ) {
				sqlAppender.appendSql( ',' );
				if ( pathElement instanceof JsonPathHelper.JsonAttribute attribute ) {
					sqlAppender.appendSingleQuoteEscapedString( attribute.attribute() );
				}
				else if ( pathElement instanceof JsonPathHelper.JsonParameterIndexAccess indexParameter) {
					final String parameterName = indexParameter.parameterName();
					throw new QueryException( "JSON path [" + jsonPath + "] uses parameter [" + parameterName + "] that is not passed" );
				}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Inline the JSON path as a string literal in the HQL: json_query(e.doc, '$.headers.status').
  2. Build the HQL dynamically with the literal path interpolated - validate/whitelist the path (no quotes, no user-controlled syntax) to avoid injection.
  3. Keep a small set of pre-built queries (one per path) and select among them at runtime.
  4. Fall back to a native SQL query where the path is a real bind parameter to SingleStore's own JSON functions.

Example fix

// before - throws: path is a bind parameter
List<String> r = session.createQuery("select json_query(e.doc, :p) from Event e", String.class)
        .setParameter("p", "$.status").getResultList();

// after - literal path
List<String> r = session.createQuery("select json_query(e.doc, '$.status') from Event e", String.class)
        .getResultList();
Defensive patterns

Strategy: fallback

Validate before calling

// Validate a dynamic path, then inline it as a literal
boolean safe = path.matches("^\$[.A-Za-z0-9_\[\]'-]*$");
if (!safe) throw new IllegalArgumentException("untrusted json path");
String hql = "select json_query(e.doc, '" + path + "') from Event e";

Try / catch

try {
    return session.createQuery(hql, String.class).getResultList();
} catch (QueryException e) {
    if (e.getMessage().contains("literal json paths")) {
        throw new IllegalArgumentException("json path must be a literal: " + path, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: HQL/JPA query like: select json_query(e.doc, :path) from Event e, then query.setParameter("path", "$.status"). Any parameter expression (named or positional) in the jsonpath argument position triggers it; string literals like '$.status' do not.

Common situations: Generic 'query any JSON path' repository APIs that bind the path at runtime; code migrated from Oracle/PostgreSQL dialects that accept parameterized paths; dynamically choosing among a set of paths without rewriting the query string.

Related errors


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