hibernate/hibernate-orm · error · IllegalStateException

Cannot instantiate class '{}' (it has no constructor with si

Error message

Cannot instantiate class '{}' (it has no constructor with signature {}, and has arguments with duplicate aliases [{}])

What it means

Thrown for `select new com.acme.Dto(...)` dynamic instantiation when no constructor matches the selected argument types and the alias-based bean-injection fallback cannot be used because two or more arguments share the same alias. The message lists the duplicated aliases. Injection needs each selected value bound to a distinct field/setter name, so duplicate aliases block it.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationResultImpl.java:188

			return new DynamicInstantiationAssemblerConstructorImpl<>( constructor, javaType, argumentReaders );
		}

		if ( LOG.isDebugEnabled() ) {
			LOG.debugf(
					"Could not locate appropriate constructor for dynamic instantiation of [%s]; attempting bean-injection instantiation",
					javaType.getTypeName()
			);
		}

		if ( !areAllArgumentsAliased) {
			throw new IllegalStateException(
					"Cannot instantiate class '" + javaType.getTypeName() + "'"
							+ " (it has no constructor with signature " + signature()
							+ ", and not every argument has an alias)"
			);
		}
		if ( !duplicatedAliases.isEmpty() ) {
			throw new IllegalStateException(
					"Cannot instantiate class '" + javaType.getTypeName() + "'"
							+ " (it has no constructor with signature " + signature()
							+ ", and has arguments with duplicate aliases ["
							+ StringHelper.join( ",", duplicatedAliases) + "])"
			);
		}

		return new DynamicInstantiationAssemblerInjectionImpl<>( javaType, argumentReaders );
	}

	private static Class<?> argumentClass(ArgumentReader<?> reader) {
		final var assembledJavaType = reader.getAssembledJavaType();
		return assembledJavaType instanceof DateJavaType temporalJavaType
				// Hack to accommodate a constructor with java.sql parameter
				// types when the entity has java.util.Date as its field types.
				// (This was requested in HHH-4179 and we fixed it by accident.)
				? TemporalJavaType.resolveJavaTypeClass( temporalJavaType.getPrecision() )
				: assembledJavaType.getJavaTypeClass();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make all aliases unique (e.g. `as orderId`, `as customerId`) so injection can map each value to a distinct property
  2. Preferably add an exact-match constructor for the selected types, which makes aliases irrelevant
  3. Check the exception message for the exact list of duplicated aliases and the constructor signature Hibernate wanted

Example fix

// before
select new org.acme.OrderDto(o.id as id, c.id as id) from Order o join o.customer c
// after
select new org.acme.OrderDto(o.id as orderId, c.id as customerId) from Order o join o.customer c
Defensive patterns

Strategy: validation

Validate before calling

// Ensure unique aliases so the injection fallback stays available
Set<String> s = new HashSet<>();
if (!s.addAll(Arrays.asList("orderId", "customerId"))) throw new IllegalArgumentException("duplicate alias");

Prevention

When it happens

Trigger: `select new org.acme.Dto(a.id as x, b.id as x)` where Dto also lacks a matching constructor; refactoring that introduced a duplicate alias into a DTO instantiation that previously relied on injection; generated HQL reusing one alias name across joined tables.

Common situations: Copy-pasted select lines in DTO instantiations; large DTO projections where duplicate aliases go unnoticed; combination of a missing constructor plus non-unique aliases after a model change.

Related errors


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