hibernate/hibernate-orm · error · InstantiationException

Unable to locate constructor for embeddable

Error message

Unable to locate constructor for embeddable

What it means

The standard embeddable instantiator resolves a no-arg constructor via ReflectHelper.getDefaultConstructor at construction time; when it is not found (PropertyNotFoundException), the code logs noDefaultConstructor and leaves this.constructor null. Later, instantiate(ValueAccess) throws InstantiationException("Unable to locate constructor for embeddable") for the mapped class because it has no usable no-arg constructor and no custom/indirecting instantiator was registered.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/internal/EmbeddableInstantiatorPojoStandard.java:55

		try {
			return getDefaultConstructor( mappedPojoClass );
		}
		catch ( PropertyNotFoundException e ) {
			CORE_LOGGER.noDefaultConstructor( mappedPojoClass.getName() );
			return null;
		}
	}

	@Override
	public Object instantiate(ValueAccess valuesAccess) {
		if ( isAbstract() ) {
			throw new InstantiationException(
					"Cannot instantiate abstract class or interface", getMappedPojoClass()
			);
		}

		if ( constructor == null ) {
			throw new InstantiationException( "Unable to locate constructor for embeddable", getMappedPojoClass() );
		}

		try {
			final var values = valuesAccess == null ? null : valuesAccess.getValues();
			final Object instance = constructor.newInstance();
			if ( values != null ) {
				// At this point, createEmptyCompositesEnabled is always true.
				// We can only set the property values on the compositeInstance though if there is at least one non null value.
				// If the values are all null, we would normally not create a composite instance at all because no values exist.
				// Setting all properties to null could cause IllegalArgumentExceptions though when the component has primitive properties.
				// To avoid this exception and align with what Hibernate 5 did, we skip setting properties if all values are null.
				// A possible alternative could be to initialize the resolved values for primitive fields to their default value,
				// but that might cause unexpected outcomes for Hibernate 5 users that use createEmptyCompositesEnabled when updating.
				// You can see the need for this by running EmptyCompositeEquivalentToNullTest
				embeddableMappingAccess.get().setValues( instance, values );
			}

			return instance;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Add an accessible no-arg constructor to the embeddable (it can be protected if the class and package are open to Hibernate; public is safest).
  2. With Lombok: add @NoArgsConstructor (optionally @AllArgsConstructor + @NoArgsConstructor(force = true) for final fields).
  3. Or keep immutable classes and register injection explicitly: compile with -parameters so the indirecting instantiator is used, or supply @EmbeddableInstantiator(MyInstantiator.class).
  4. For records, rely on the record instantiator path (ensure the class really is a record) rather than expecting a no-arg constructor.

Example fix

// before
@Embeddable
public class Period {
    private final LocalDate start;
    private final LocalDate end;
    public Period(LocalDate start, LocalDate end) { ... } // no no-arg ctor
}

// after (Lombok)
@Embeddable
@NoArgsConstructor(force = true)
@AllArgsConstructor
public class Period {
    private LocalDate start;
    private LocalDate end;
}
Defensive patterns

Strategy: type-guard

Validate before calling

// before bootstrap: every embeddable needs a no-arg ctor OR an explicit instantiator
static void checkNoArgCtor(Class<?> embeddable) {
    try {
        Constructor<?> c = embeddable.getDeclaredConstructor();
        if (!Modifier.isPublic(c.getModifiers()) && !c.canAccess(null))
            throw new IllegalStateException("no-arg ctor of " + embeddable + " not accessible");
    } catch (NoSuchMethodException e) {
        throw new IllegalStateException("Embeddable missing no-arg constructor: " + embeddable.getName(), e);
    }
}

Type guard

static boolean hasAccessibleNoArgConstructor(Class<?> embeddable) {
    try {
        Constructor<?> c = embeddable.getDeclaredConstructor();
        c.setAccessible(true);
        return true;
    } catch (NoSuchMethodException | InaccessibleObjectException e) {
        return false;
    }
}

Prevention

When it happens

Trigger: An @Embeddable class defining only parameterized constructors (no explicit no-arg one), used with @Embedded/@EmbeddedId, where constructor injection was not selected (class not compiled with -parameters, or the mapping did not resolve an instantiator), leaving PojoStandard as the instantiator; private no-arg constructors in classes/package not open to Hibernate can effectively behave the same at lookup time.

Common situations: Java classes with only field-populating constructors (e.g. Lombok @AllArgsConstructor without @NoArgsConstructor); Kotlin data classes without a no-arg plugin; Java records accidentally mapped as plain embeddables (no canonical-constructor path selected); value classes designed immutable without a default ctor; JPMS not opening the package so getDefaultConstructor fails.

Related errors


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