hibernate/hibernate-orm · error · InstantiationException
Cannot instantiate query result type, found no matching cons
Error message
Cannot instantiate query result type, found no matching constructor
What it means
Thrown while building RowTransformerConstructorImpl: the tuple element Java types were resolved, but no constructor of the requested result class matches them (wrong count, order, or types). In the standard SQM path this is caught at ConcreteSqmSelectQueryPlan:371 and the checking transformer takes over, so you frequently see the QueryTypeMismatchException of error 3186 at execution time instead; the raw message surfaces through construction paths without that catch (e.g. ConcreteSqmSelectQueryPlan:339).
Source
Thrown at hibernate-core/src/main/java/org/hibernate/sql/results/internal/RowTransformerConstructorImpl.java:46
public RowTransformerConstructorImpl(
Class<T> type,
TupleMetadata tupleMetadata,
TypeConfiguration typeConfiguration) {
this.type = type;
assert tupleMetadata != null : "TupleMetadata must not be null";
final List<TupleElement<?>> elements = tupleMetadata.getList();
final List<Class<?>> argumentTypes = elements.stream()
.map( RowTransformerConstructorImpl::resolveElementJavaType )
.collect( toList() );
if ( argumentTypes.size() == 1 && argumentTypes.get( 0 ) == null ) {
// Can not (properly) resolve constructor for single null element
throw new InstantiationException( "Cannot instantiate query result type, argument types are unknown ", type );
}
constructor = findMatchingConstructor( type, argumentTypes, typeConfiguration );
if ( constructor == null ) {
throw new InstantiationException( "Cannot instantiate query result type, found no matching constructor", type );
}
constructor.setAccessible( true );
}
private static Class<?> resolveElementJavaType(TupleElement<?> element) {
if ( element instanceof SqmExpressibleAccessor<?> accessor ) {
final SqmExpressible<?> expressible = accessor.getExpressible();
if ( expressible != null && expressible.getExpressibleJavaType() != null ) {
return expressible.getExpressibleJavaType().getJavaTypeClass();
}
}
return element.getJavaType();
}
@Override
public T transformRow(Object[] row) {
try {View on GitHub (pinned to fad1729dce)
Solutions
- Add a constructor to the result class whose parameter list matches the selected expressions exactly (count, order, types) - prefer boxed types matching Hibernate's resolution (e.g. Long for ids and counts)
- Print the tuple types first by querying with `Object[].class`, then write the constructor to fit
- If the class is out of your control, switch to `select new your.Dto(...)`-style injection of an adaptable DTO, or query Tuple/Object[] and map manually
Example fix
// before
public NameSalaryDto(String name, int salary) { ... }
List<NameSalaryDto> l = em.createQuery("select e.name, e.salary from Employee e", NameSalaryDto.class).getResultList(); // salary resolves to BigDecimal
// after
public NameSalaryDto(String name, java.math.BigDecimal salary) { ... } Defensive patterns
Strategy: validation
Validate before calling
// Print the resolved tuple types, then write the constructor to match exactly
Object[] row = em.createQuery("select e.name, e.salary from Employee e", Object[].class).setMaxResults(1).getSingleResult();
Arrays.stream(row).forEach(v -> System.out.println(v == null ? "null" : v.getClass().getName())); Try / catch
catch (org.hibernate.InstantiationException e) { if (e.getMessage().contains("no matching constructor")) { /* align DTO ctor with printed tuple types */ } throw e; } Prevention
- Keep DTO constructors generated next to the query (mapstruct/codegen) so they cannot drift
- Prefer boxed types and BigDecimal/Long for numerics; JDBC aggregates are rarely int
- After schema or dialect changes, re-run projection probe tests that assert tuple Java types
When it happens
Trigger: `em.createQuery("select e.name, e.salary from Employee e", NameSalaryDto.class)` where NameSalaryDto has no `(String, BigDecimal)` constructor; DTO constructor expects `int`/`Integer` but selection resolves to `Long`; arguments selected in a different order than the constructor parameters.
Common situations: DTO and entity drift after refactors; database dialect changes that alter the Java type of an aggregate (`count` returning Long vs Integer); adding a column to the projection without updating the DTO.
Related errors
- Result type is '{}' but the query returned a '{}'
- Parameter %d of function '%s()' has type '%s', but argument
- Incorrect query result type: query produces '%s' but type '%
- Cannot instantiate class '{}' (it has no constructor with si
- Function %s() has %d parameters, but %d arguments given
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/380a88a97d48b499.
Report an issue: GitHub.