hibernate/hibernate-orm · error · InstantiationException

Error instantiating class '{}' using default constructor: {}

Error message

Error instantiating class '{}' using default constructor: {}

What it means

Injection-style dynamic instantiation first creates the target instance via its declared no-arg constructor (getDeclaredConstructor() + setAccessible + newInstance) before applying bean injections. If the class has no no-arg constructor, or it cannot be invoked (private constructor in a closed module, non-static inner class requiring an enclosing instance), the reflection exception is wrapped as InstantiationException("Error instantiating class '<class>' using default constructor: <message>").

Source

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

	}

	@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();
		}
		catch ( NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException
				| java.lang.InstantiationException e ) {
			throw new InstantiationException( "Error instantiating class '"
					+ target.getTypeName() + "' using default constructor: " + e.getMessage(), e );
		}
		for ( var beanInjection : beanInjections ) {
			final Object assembled = beanInjection.getValueAssembler().assemble( rowProcessingState );
			beanInjection.getBeanInjector().inject( result, assembled );
		}
		return result;
	}

	@Override
	public void resolveState(RowProcessingState rowProcessingState) {
		for ( var beanInjection : beanInjections ) {
			beanInjection.getValueAssembler().resolveState( rowProcessingState );
		}
	}

	@Override
	public <X> void forEachResultAssembler(BiConsumer<Initializer<?>, X> consumer, X arg) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Add a public no-arg constructor to the target class (this path requires it), keeping setters/fields writable for the aliases.
  2. If you want construction control, define an explicit constructor matching the select items - Hibernate will use the constructor path instead of injection.
  3. For Kotlin, add a secondary constructor or apply the kotlin-noarg plugin for the DTO.
  4. Ensure the class is a top-level or public static nested class and its package is open to reflection when running modularized.

Example fix

// before
public class StatsDto {
    public StatsDto(String region, Long total) { ... } // no default constructor
}

// after - keep the explicit ctor AND add the no-arg ctor for injection
public class StatsDto {
    public StatsDto() { }
    public StatsDto(String region, Long total) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

// At startup, verify the injection target has an invokable no-arg constructor
Constructor<?> c;
try {
    c = StatsDto.class.getDeclaredConstructor();
} catch (NoSuchMethodException e) {
    throw new IllegalStateException("StatsDto needs a no-arg constructor for bean-injection instantiation", e);
}
if (!Modifier.isPublic(c.getModifiers()) && !c.trySetAccessible()) {
    throw new IllegalStateException("no-arg constructor of StatsDto is not accessible");
}

Type guard

// Reflective guard: type is usable for injection-style instantiation
static boolean hasUsableNoArgCtor(Class<?> dto) {
    try {
        Constructor<?> c = dto.getDeclaredConstructor();
        return Modifier.isPublic(c.getModifiers()) || c.trySetAccessible();
    } catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
    rows = q.getResultList();
} catch (org.hibernate.query.sqm.sql.internal.InstantiationException e) {
    if (String.valueOf(e.getMessage()).contains("using default constructor")) {
        // add a public no-arg constructor, or switch to an explicit constructor expression
    }
}

Prevention

When it happens

Trigger: `select new com.acme.Dto(...) ...` where the injection path was chosen (no matching all-args constructor) but Dto defines only parameterized constructors; a private no-arg constructor under JPMS where setAccessible fails; a non-static inner class as the target (its hidden constructor needs the outer instance).

Common situations: DTOs that 'grew' an all-args constructor so the implicit default constructor disappeared; immutable-style DTOs with only final-field constructors; Kotlin data classes without a no-arg secondary constructor; Java 9+ module access rules.

Related errors


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