hibernate/hibernate-orm · error · InstantiationException

Could not instantiate entity

Error message

Could not instantiate entity

What it means

Hibernate throws this org.hibernate.InstantiationException while materializing an embeddable mapped as a Java record, when the record's canonical constructor invocation fails. This instantiator (EmbeddableInstantiatorRecordIndirecting) re-orders the values read from the database into record-component order using its index array and then calls constructor.newInstance(values); any exception thrown by that call (NPE from validation, failed unboxing, IllegalAccessException in modular setups) is wrapped in this InstantiationException with the original as its cause.

Solutions

  1. Inspect the cause chain of the InstantiationException (getCause()) - it names the real constructor failure
  2. If columns can be null, use wrapper types in the record and remove null-rejecting checks (Objects.requireNonNull) from the compact constructor
  3. Declare columns NOT NULL in the schema if the record genuinely must reject nulls
  4. Register a custom instantiator with @org.hibernate.annotations.EmbeddableInstantiator (or @IdMappedInstantiator for id embeddables) that converts raw values defensively before calling the constructor
  5. If running under JPMS, add 'opens <entity.package> to hibernate.core' (or hibernate.orm.core) in module-info.java

Example fix

// before - compact constructor rejects nulls from nullable columns
public record Address(String street, String zip) {
    public Address {
        Objects.requireNonNull(street);
    }
}

// after - tolerate nulls, or provide a custom instantiator
public record Address(String street, String zip) {
}

// or, map a default with a custom instantiator
public class AddressInstantiator implements EmbeddableInstantiator {
    @Override
    public Object instantiate(ValueAccess valuesAccess) {
        Object[] v = valuesAccess.getValues();
        return new Address( v[0] == null ? "" : (String) v[0], (String) v[1] );
    }
}

@Embeddable
@EmbeddableInstantiator(AddressInstantiator.class)
public record Address(String street, String zip) {}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before loading, verify nullable columns match null-tolerant record components
boolean safe = true;
for (RecordComponent rc : Address.class.getRecordComponents()) {
    if ( rc.getType().isPrimitive() && columnNullable( rc.getName() ) ) safe = false;
}
if ( !safe ) throw new IllegalStateException("Primitive record component mapped to nullable column");

Try / catch

try {
    return session.find(User.class, id);
}
catch ( org.hibernate.InstantiationException e ) {
    // e.getCause() holds the real constructor failure (NPE, IllegalArgument, ...)
    log.warn("Row {} has embeddable data the record rejects: {}", id, e.getCause());
    return null;
}

Prevention

When it happens

Trigger: Loading or querying a row into an @Embedded/@EmbeddedId record whose compact constructor throws (e.g. Objects.requireNonNull) because a mapped column is null; a record component declared as a primitive (int, boolean) receiving a null column value causing NullPointerException during unboxing; the record living in a Java module (module-info) that does not open its package to hibernate.core, making the canonical constructor inaccessible via reflection.

Common situations: Teams adopting Java records for embeddables with null-validation in compact constructors while the schema still allows NULLs; migrating embeddable fields from wrapper types to primitives; JPQL/Criteria loads of entities containing such embeddables; strong encapsulation under JPMS after moving entities into named modules.

Related errors


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

Appendix: source

Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorRecordIndirecting.java:47

				: new EmbeddableInstantiatorRecordIndirecting( javaType, index );
	}

	@Override
	public Object instantiate(ValueAccess valuesAccess) {
		if ( constructor == null ) {
			throw new InstantiationException( "Unable to locate constructor for embeddable", getMappedPojoClass() );
		}

		try {
			final var originalValues = valuesAccess.getValues();
			final var values = new Object[originalValues.length];
			for ( int i = 0; i < values.length; i++ ) {
				values[i] = originalValues[index[i]];
			}
			return constructor.newInstance( values );
		}
		catch ( Exception e ) {
			throw new InstantiationException( "Could not instantiate entity", getMappedPojoClass(), e );
		}
	}

	// Handles gaps, by leaving the value null for that index
	private static class EmbeddableInstantiatorRecordIndirectingWithGap
			extends EmbeddableInstantiatorRecordIndirecting {

		public EmbeddableInstantiatorRecordIndirectingWithGap(Class<?> javaType, int[] index) {
			super( javaType, index );
		}

		@Override
		public Object instantiate(ValueAccess valuesAccess) {
			if ( constructor == null ) {
				throw new InstantiationException( "Unable to locate constructor for embeddable", getMappedPojoClass() );
			}

			try {

View on GitHub (pinned to fad1729dce)