hibernate/hibernate-orm · error · InstantiationException
Cannot set field '{}' to instantiate '{}'
Error message
Cannot set field '{}' to instantiate '{}' What it means
For injection-style dynamic instantiation (select new with a no-arg-constructible target), DynamicInstantiationAssemblerInjectionImpl.injection() tries, per argument, first a matching JavaBean property (name plus compatible type via propertyMatches) and then a field with the alias name and compatible type (findField). If neither exists for an argument's alias, it throws InstantiationException("Cannot set field '<alias>' to instantiate '<target class>'") at query-plan build time: the query aliases do not line up with any setter or field on the target.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerInjectionImpl.java:75
final var argType = argument.getAssembledJavaType().getJavaTypeClass();
final String alias = argument.getAlias();
// see if we can find a property with the given name...
for ( var propertyDescriptor : beanInfo.getPropertyDescriptors() ) {
if ( propertyMatches( alias, argType, propertyDescriptor ) ) {
final var setter = propertyDescriptor.getWriteMethod();
setter.setAccessible(true);
return new BeanInjection( new BeanInjectorSetter<>( setter ), argument );
}
}
// see if we can find a Field with the given name...
final var field = findField( targetJavaType, alias, argType );
if ( field != null ) {
return new BeanInjection( new BeanInjectorField<>( field ), argument );
}
else {
throw new InstantiationException(
"Cannot set field '" + alias + "' to instantiate '" + targetJavaType.getName() + "'"
);
}
}
@Override
public JavaType<T> getAssembledJavaType() {
return target;
}
@Override
@SuppressWarnings("unchecked")
public T assemble(RowProcessingState rowProcessingState) {
final T result;
try {
final var constructor = target.getJavaTypeClass().getDeclaredConstructor();
constructor.setAccessible( true );
result = constructor.newInstance();View on GitHub (pinned to fad1729dce)
Solutions
- Make every select-item alias match, by name and type, a setter (or field) on the target class - exact spelling and an assignable type.
- Add the missing property (field plus setter) with the aliased name, or rename the alias in the query to the existing property.
- If types cannot match, switch to a constructor expression with an explicit constructor for full control.
- Cover every dynamic-instantiation query with a startup smoke test (createQuery plus execution on test data) so the failure is caught at build time, not production.
Example fix
// before
public class EmpDto { private String fullName; /* no 'nm' */ }
em.createQuery("select new com.acme.EmpDto(e.name as nm) from Employee e", EmpDto.class);
// -> Cannot set field 'nm' to instantiate 'com.acme.EmpDto'
// after
em.createQuery("select new com.acme.EmpDto(e.name as fullName) from Employee e", EmpDto.class); Defensive patterns
Strategy: validation
Validate before calling
// At startup, verify every query alias has a matching, type-compatible setter or field
Set<String> props = new HashSet<>();
for (PropertyDescriptor pd : Introspector.getBeanInfo(EmpDto.class).getPropertyDescriptors())
if (pd.getWriteMethod() != null) props.add(pd.getName());
for (Field f : EmpDto.class.getDeclaredFields()) props.add(f.getName());
for (String alias : List.of("fullName" /* aliases used in the query */)) {
if (!props.contains(alias))
throw new IllegalStateException("alias '" + alias + "' has no setter/field on EmpDto");
} Type guard
// Reflective guard: alias must resolve to an injectable member
static boolean aliasInjectable(Class<?> dto, String alias, Class<?> assembled) {
try {
for (PropertyDescriptor pd : Introspector.getBeanInfo(dto).getPropertyDescriptors())
if (pd.getName().equals(alias) && pd.getWriteMethod() != null
&& pd.getWriteMethod().getParameterTypes()[0].isAssignableFrom(assembled))
return true;
return dto.getDeclaredField(alias).getType().isAssignableFrom(assembled);
} catch (IntrospectionException | NoSuchFieldException e) { return false; }
} Try / catch
try {
rows = q.getResultList();
} catch (org.hibernate.query.sqm.sql.internal.InstantiationException e) {
if (String.valueOf(e.getMessage()).startsWith("Cannot set field '")) {
// the message names the bad alias and target class: add the property or fix the alias
}
} Prevention
- Keep query aliases and DTO property names identical - one vocabulary, maintained together.
- Build a startup check that validates aliases against the DTO for every projection query.
- Change aliases and DTO fields in one commit; grep for the alias string project-wide.
When it happens
Trigger: `select new com.acme.Dto(o.name as nm, o.age as yrs) ...` where Dto has no setNm/nm field and no setYrs/yrs field; alias matches a property but the argument type is incompatible, so the property check fails AND no same-named field with the right type exists (type compatibility is part of matching); typos or casing mismatches between alias and property name.
Common situations: Renaming DTO properties or query aliases independently; adding a new select item with an alias the DTO never got; alias/property type drift after model changes (e.g. property changed from int to String so propertyMatches no longer accepts); query and DTO updated in different commits.
Related errors
- Error performing the dynamic instantiation
- Error instantiating class '{}'
- Error instantiating class '{}' using default constructor: {}
- dynamic instantiation in a sub-query is unsupported
- Injection of parent instance into embeddable result is not p
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/9b2b1b8d889562db.
Report an issue: GitHub.