hibernate/hibernate-orm · error · QueryException

Json path expression expression emulation only supports abso

Error message

Json path expression expression emulation only supports absolute paths i.e. must start with a '$' but got: {jsonPath}

What it means

Hibernate JSON path emulation only accepts absolute paths. parseJsonPathElements checks the first character and requires '$'. Any path starting with something else, for example 'name' or '.name', throws this QueryException during SQL rendering.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/json/JsonPathHelper.java:21

 * Copyright Red Hat Inc. and Hibernate Authors
 */
package org.hibernate.dialect.function.json;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.hibernate.QueryException;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JsonPathPassingClause;

public class JsonPathHelper {

	public static List<JsonPathElement> parseJsonPathElements(String jsonPath) {
		if ( jsonPath.charAt( 0 ) != '$' ) {
			throw new QueryException( "Json path expression expression emulation only supports absolute paths i.e. must start with a '$' but got: " + jsonPath );
		}
		final var jsonPathElements = new ArrayList<JsonPathElement>();
		int startIndex;
		int dotIndex;

		if ( jsonPath.length() > 1 ) {
			if ( jsonPath.charAt( 1 ) == '.' ) {
				startIndex = 2;
			}
			else {
				final int bracketEndIndex = jsonPath.indexOf( ']' );
				parseBracket( jsonPath, 1, bracketEndIndex, jsonPathElements );
				startIndex = bracketEndIndex + 2;
			}

			try {
				while ( ( dotIndex = jsonPath.indexOf( '.', startIndex ) ) != -1 ) {
					parseAttribute( jsonPath, startIndex, dotIndex, jsonPathElements );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Prefix the path with the root: use '$.customer.name'.
  2. Normalize user-supplied paths once at the application boundary: prepend '$' and '.' when missing.
  3. Use the strict root form even for single segments: '$.name', not 'name'.

Example fix

// before
select json_value(e.doc, 'customer.name') from Entity e

// after
select json_value(e.doc, '$.customer.name') from Entity e
Defensive patterns

Strategy: validation

Validate before calling

static String normalizeJsonPath(String path) {
    if (path == null || path.isBlank()) {
        throw new IllegalArgumentException("JSON path is empty");
    }
    if (path.charAt(0) != '$') {
        path = "$" + (path.charAt(0) == '.' ? "" : ".") + path;
    }
    return path;
}
String safe = normalizeJsonPath(userInput); // 'customer.name' -> '$.customer.name'

Type guard

static boolean isAbsoluteJsonPath(String path) {
    return path != null && !path.isEmpty() && path.charAt(0) == '$';
}

Try / catch

try {
    return session.createQuery(hql, String.class).getSingleResult();
} catch (org.hibernate.QueryException e) {
    if (e.getMessage() != null && e.getMessage().contains("must start with a '$'")) {
        throw new IllegalArgumentException("Reject or normalize the supplied JSON path", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: A json_value, json_query, or json_exists call passes a path without the root sign: json_value(doc, 'customer.name'). The charAt(0) check fails and the error includes the offending path.

Common situations: Paths copied from JavaScript or MongoDB style access. User input used for the path without normalization. Migrating raw SQL where the database accepted lax paths.

Related errors


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