hibernate/hibernate-orm · error · MappingException

Generator '%s' declares generated type '%s', which is not as

Error message

Generator '%s' declares generated type '%s', which is not assignable to generated attribute '%s' of type '%s'

What it means

When a Generator declares the type of value it produces (getGeneratedType() returns a non-null Class), Hibernate validates at bootstrap that the produced type is assignable to the attribute the generator is attached to (boxing-aware via boxedType). If, for example, a UUID-producing generator is attached to a Long id, this MappingException is thrown, naming the generator class, generated type, attribute path, and attribute type.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/generator/internal/GeneratorTypeHelper.java:32

import static org.hibernate.internal.util.PrimitiveHelper.boxedType;

@Internal
public final class GeneratorTypeHelper {
	public static void checkGeneratorGeneratedType(Generator generator, GeneratorCreationContext context) {
		final var generatedType = generator.getGeneratedType();
		if ( generatedType != null ) {
			final var property = context.getProperty();
			if ( property != null ) {
				checkAssignable( generator, generatedType, context );
			}
		}
	}

	private static void checkAssignable(Generator generator, Class<?> generatedType, GeneratorCreationContext context) {
		final var attributeType = context.getType().getReturnedClass();
		if ( attributeType != null
				&& !boxedType( attributeType ).isAssignableFrom( boxedType( generatedType ) ) ) {
			throw new MappingException( String.format(
					Locale.ROOT,
					"Generator '%s' declares generated type '%s', which is not assignable to generated attribute '%s' of type '%s'",
					generator.getClass().getName(),
					generatedType.getTypeName(),
					attributePath( context ),
					attributeType.getTypeName()
			) );
		}
	}

	private static String attributePath(GeneratorCreationContext context) {
		final var property = context.getProperty();
		final var persistentClass = context.getPersistentClass();
		if ( persistentClass != null && property != null ) {
			return persistentClass.getEntityName() + "." + property.getName();
		}

		final var memberDetails = context.getMemberDetails();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Align the types: change the attribute to the generated type (Long id -> UUID id) or change the generator to produce the attribute's type
  2. If one generator must serve several attribute types, return null from getGeneratedType() to opt out of the static check and generate values matching each attribute
  3. Pick the built-in generator matching the attribute type (@UuidGenerator for UUID, sequence/identity for integral ids)
  4. Add a unit test asserting getGeneratedType() is assignable to every attribute carrying your generator annotation

Example fix

// before — generator produces UUID, attribute is Long
@Id
@MyUuidGenerator
Long id;

// after — attribute type matches the generated type
@Id
@MyUuidGenerator
UUID id;
Defensive patterns

Strategy: type-guard

Validate before calling

@Test
void generatorMatchesAttributeTypes() throws Exception {
    MyUuidGenerator g = new MyUuidGenerator();
    assertEquals(UUID.class, g.getGeneratedType());
    assertEquals(UUID.class, Document.class.getDeclaredField("id").getType());
}

Type guard

static boolean generatorCompatible(Generator generator, Class<?> attributeJavaType) {
    final Class<?> generated = generator.getGeneratedType();
    return generated == null || attributeJavaType == null
            || box(attributeJavaType).isAssignableFrom(box(generated));
}

static Class<?> box(Class<?> t) {
    if (!t.isPrimitive()) return t;
    if (t == int.class) return Integer.class;
    if (t == long.class) return Long.class;
    if (t == boolean.class) return Boolean.class;
    if (t == double.class) return Double.class;
    if (t == float.class) return Float.class;
    if (t == short.class) return Short.class;
    if (t == byte.class) return Byte.class;
    return Character.class;
}

Prevention

When it happens

Trigger: Attaching a generator whose declared type mismatches the attribute: a custom Generator via @IdGeneratorType or generator strategies — e.g. UUID generator on a Long id, Integer generator on a String field, java.util.Date generator on a java.time.Instant attribute.

Common situations: Writing the first custom @IdGeneratorType annotation by copying an example written for another attribute type; changing an entity field type without updating its generator; applying one custom generator annotation to several entities whose id types differ.

Related errors


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