hibernate/hibernate-orm · error · AnnotationException

Unable to create AttributeConverter instance

Error message

Unable to create AttributeConverter instance

What it means

AbstractPropertyHolder.makeAttributeConverterDescriptor creates the ConverterDescriptor for each @Convert(converter = ...) it processes, by calling ConverterDescriptors.of(...). That path (ClassBasedConverterDescriptor -> AbstractConverterDescriptor) resolves the converter class's AttributeConverter<X,Y> generic type arguments and reads its @Converter annotation; any failure - class does not implement AttributeConverter, unresolvable generic signature, abstract/interface class, class loading error - is wrapped in this AnnotationException with the original cause attached.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AbstractPropertyHolder.java:141

		}
		else {
			return new IllegalStateException(
					String.format(
							"Unable to instantiate AttributeConverter [%s]",
							info.getConverterClass().getName()
					),
					e
			);
		}
	}

	protected ConverterDescriptor<?,?> makeAttributeConverterDescriptor(AttributeConversionInfo conversion) {
		try {
			return ConverterDescriptors.of( conversion.getConverterClass(), null, false );
		}
		catch (Exception e) {
			throw new AnnotationException( "Unable to create AttributeConverter instance", e );
		}
	}

	@Override
	public boolean isInIdClass() {
		if ( isInIdClass != null ) {
			return isInIdClass;
		}
		else if ( parent != null ) {
			return parent.isInIdClass();
		}
		else {
			return false;
		}
	}

	@Override
	public void setInIdClass(Boolean isInIdClass) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Inspect the attached cause (getCause()) - it names the real reflection/generics failure
  2. Make the converter a public concrete class: public class MyConverter implements AttributeConverter<DomainType, JdbcType> with concrete type arguments
  3. Give it a public no-arg constructor so Hibernate's bean registry can instantiate it
  4. Verify there is exactly one MyConverter class on the classpath (check for duplicated artifacts)
  5. For nested classes use the binary name, e.g. @Convert(converter = Outer$MyConverter.class), and declare it public static

Example fix

// before: class does not implement AttributeConverter -> boot fails
public class StatusConverter {                 // missing 'implements'
    public String convertToDatabaseColumn(Status s) { ... }
}
@Convert(converter = StatusConverter.class)
private Status status;

// after
public class StatusConverter
        implements AttributeConverter<Status, String> {   // concrete type args
    @Override public String convertToDatabaseColumn(Status s) { ... }
    @Override public Status convertToEntityAttribute(String db) { ... }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before boot: every @Convert converter class must be a concrete AttributeConverter
static boolean converterClassIsValid(Class<?> c) {
    return AttributeConverter.class.isAssignableFrom(c)
            && !c.isInterface()
            && !Modifier.isAbstract(c.getModifiers())
            && Arrays.stream(c.getConstructors()).anyMatch(ctor -> ctor.getParameterCount() == 0);
}

Try / catch

try {
    sessionFactory = new MetadataSources(registry)
            .addAnnotatedClass(MyEntity.class).buildMetadata().buildSessionFactory();
} catch (AnnotationException e) {
    if (e.getMessage().contains("Unable to create AttributeConverter instance")) {
        Throwable cause = e.getCause();          // real reflection failure is chained
        throw new IllegalStateException("Broken @Convert converter class: " + cause, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: An entity attribute carries @Convert(converter = X.class) where X is not a concrete AttributeConverter implementation, has unresolvable generic parameters, or cannot be loaded; the same happens for converters registered by class through the bootstrap API whose class shape is invalid.

Common situations: Refactoring that turns a converter into an interface or abstract base; copy-pasting @Convert without implementing the interface; duplicate/inconsistent converter classes on the classpath after a dependency merge; obfuscated or instrumented classes whose generic signatures are stripped.

Related errors


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