hibernate/hibernate-orm · error · QueryException

JSON path [{}] uses parameter [{}] that is not passed

Error message

JSON path [{}] uses parameter [{}] that is not passed

What it means

Hibernate's JSON path syntax allows parameter markers inside brackets (e.g. 'items[$i]') that must be supplied through a PASSING clause. The SingleStore json_array_append emulation has no passing support and renders each path element as a constant, so buildJsonPath throws QueryException the moment it encounters a JsonParameterIndexAccess element whose parameter was not passed.

Source

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

	private static boolean isNumeric(SqlAstNode value) {
		return value instanceof UnparsedNumericLiteral<?>;
	}

	private static void buildJsonArrayPushValue(SqlAppender sqlAppender, SqlAstNode value) {
		sqlAppender.appendSql( "json_array_push_" );
		sqlAppender.appendSql( isNumeric( value ) ? "double(" : "string(" );
	}

	private static void buildJsonPath(
			SqlAppender sqlAppender, Expression jsonPath, List<JsonPathHelper.JsonPathElement> jsonPathElements) {
		for ( JsonPathHelper.JsonPathElement pathElement : jsonPathElements ) {
			sqlAppender.appendSql( ',' );
			if ( pathElement instanceof JsonPathHelper.JsonAttribute attribute ) {
				sqlAppender.appendSingleQuoteEscapedString( attribute.attribute() );
			}
			else if ( pathElement instanceof JsonPathHelper.JsonParameterIndexAccess indexParameter) {
				throw new QueryException( "JSON path [" + jsonPath + "] uses parameter [" + indexParameter.parameterName() + "] that is not passed" );
			}
			else {
				sqlAppender.appendSql( '\'' );
				sqlAppender.appendSql( ( (JsonPathHelper.JsonIndexAccess) pathElement ).index() );
				sqlAppender.appendSql( '\'' );
			}
		}
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Inline the concrete index into the path string in Java (e.g. 'items[3]') before binding
  2. Render the whole path as a literal per index and execute one statement per position
  3. Keep json_array_append calls on SingleStore limited to fully literal paths
  4. Use a native SingleStore statement for dynamic paths

Example fix

// before (path contains parameter marker $i)
json_array_append(e.doc, 'items[$i]', :v)

// after: build literal path in Java
String path = "items[" + index + "]";
em.createQuery("update E e set e.doc = json_array_append(e.doc, '" + path + "', :v)")
    .setParameter("v", v).executeUpdate();
Defensive patterns

Strategy: validation

Validate before calling

// Reject $-parameter markers in JSON paths before executing on SingleStore
private static final Pattern PARAM_IN_PATH = Pattern.compile("\\[\\s*\\$\\w+");
static String requireLiteralPath(String path) {
    if (PARAM_IN_PATH.matcher(path).find()) {
        throw new IllegalArgumentException("Inline the index instead of [$param]: " + path);
    }
    return path;
}

Try / catch

try {
    em.createQuery(hql).executeUpdate(); // json_array_append with [$i] path
} catch (QueryException e) {
    if (e.getMessage() != null && e.getMessage().contains("that is not passed")) {
        // rebuild the path with a concrete index and retry
    }
    throw e;
}

Prevention

When it happens

Trigger: HQL `json_array_append(e.doc, 'items[$i]', :v)` (any path literal containing a [$name] segment) on SingleStoreDialect, with or without a passing clause.

Common situations: Dynamic array indexing code shared with PostgreSQL-style dialects that honor passing; generated queries that parameterize positions inside JSON paths.

Related errors


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