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

  1. 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)
  2. Print the tuple types first by querying with `Object[].class`, then write the constructor to fit
  3. 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

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


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