quarkusio/quarkus · error · PanacheQueryException
Unable to perform a projection on a 'select [distinct]? new'
Error message
Unable to perform a projection on a 'select [distinct]? new' query: ${query} What it means
project(Class) builds a projection query; it refuses queries using 'select new ...' constructor expressions because Panache's projection mechanism cannot rewrite them, throwing PanacheQueryException with the offending query text.
Source
Thrown at extensions/panache/hibernate-reactive-panache-common/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/common/runtime/CommonAbstractPanacheQueryImpl.java:111
protected abstract void disableFilter(SessionType session, String filter);
// Builder
public CommonAbstractPanacheQueryImpl<Entity, SessionType> sort(Sort sort) {
this.sort = sort;
return this;
}
public <T> CommonAbstractPanacheQueryImpl<T, SessionType> project(Class<T> type) {
String selectQuery = query;
if (PanacheJpaUtil.isNamedQuery(query)) {
selectQuery = NamedQueryUtil.getNamedQuery(query.substring(1));
}
String lowerCasedTrimmedQuery = PanacheJpaUtil.trimForAnalysis(selectQuery);
if (lowerCasedTrimmedQuery.startsWith("select new ")
|| lowerCasedTrimmedQuery.startsWith("select distinct new ")) {
throw new PanacheQueryException("Unable to perform a projection on a 'select [distinct]? new' query: " + query);
}
// If the query starts with a select clause, we pass it on to ORM which can handle that via a projection type
if (lowerCasedTrimmedQuery.startsWith("select ")) {
// I think projections do not change the result count, so we can keep the custom count query
return newQuery(query, customCountQueryForSpring, type);
}
// FIXME: this assumes the query starts with "FROM " probably?
// build select clause with a constructor expression
String selectClause = "SELECT " + getParametersFromClass(type, null);
// I think projections do not change the result count, so we can keep the custom count query
return newQuery(selectClause + selectQuery, customCountQueryForSpring, null);
}
private StringBuilder getParametersFromClass(Class<?> type, String parentParameter) {
BiFunction<Class<?>, String, String> nestedProjectionBuilder = (nestedType, parameterName) -> getParametersFromClass(View on GitHub (pinned to e1c734241f)
Solutions
- Remove the 'select new' clause and use a plain 'from Entity' query with .project(Dto.class)
- If you need constructor expressions, drop .project() and use the 'select new' query directly with the DTO as result type
- For named queries, keep the ORDER/simple select and project from the entity query
Example fix
// before
find("select new com.acme.Dto(p.name) from Person p").project(Dto.class)
// after
find("from Person p").project(Dto.class)
// or without project():
find("select new com.acme.Dto(p.name) from Person p").list() Defensive patterns
Strategy: validation
Validate before calling
String q = namedQuery ? NamedQueryUtil.getNamedQuery(panacheQuery.substring(1)) : panacheQuery;
String lower = q.toLowerCase().trim();
if (lower.startsWith("select new ") || lower.startsWith("select distinct new "))
throw new IllegalArgumentException("Cannot combine .project() with a 'select new' query"); Try / catch
try {
return pq.project(Dto.class);
} catch (PanacheQueryException e) {
if (e.getMessage() != null && e.getMessage().contains("select [distinct]? new")) {
throw new IllegalArgumentException("Use the 'select new' query directly instead of .project()", e);
}
throw e;
} Prevention
- Use .project(Dto.class) only on 'from Entity' or plain 'select' queries
- Rely on project() instead of writing 'select new' constructor expressions, or vice versa — pick one
- Check named query text before adding .project() calls
When it happens
Trigger: Calling .project(X.class) on a PanacheQuery created from an HQL string starting with 'select new ' or 'select distinct new ', including a '#'-named query resolving to such a query.
Common situations: Combining a constructor-expression DTO query with project(); copying a native 'select new' snippet into a panache query then adding projection; generic query builders that always call project().
Related errors
- Unable to perform a projection on a 'select [distinct]? new'
- %s entities do not support being attached to several persist
- Sort cannot be used with named query, add an "order by" clau
- Entity '%s' was not found. Did you forget to annotate your P
- Cannot call a page related method, call page(Page) or page(i
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/148ba77ec691fdf9.
Report an issue: GitHub.