spring-projects/spring-framework · error · AotBeanProcessingException
instance supplier is not supported
Error message
instance supplier is not supported
What it means
Thrown as an AotBeanProcessingException with 'instance supplier is not supported' when DefaultBeanRegistrationCodeFragments.getTarget is called for a bean whose merged bean definition has a non-null InstanceSupplier. AOT codegen cannot statically reproduce an arbitrary programmatic instance supplier, so it refuses to compute the target class for the bean.
Solutions
- Refactor the bean to a class Spring can instantiate via constructor or factory method (remove the InstanceSupplier).
- If you must keep dynamic creation, exclude the bean from AOT processing or use BeanFactory instrumentation at runtime rather than registration time.
- Move the dynamic logic inside a @Bean method that returns a concrete type Spring can analyze.
- Register an explicit RootBeanDefinition with setBeanClass/setFactoryMethodName instead of an instance supplier.
- Upgrade Spring: some suppliers added by older Boot versions are AOT-incompatible; newer Boot avoids them.
Example fix
// before: programmatic instance supplier that breaks AOT
context.registerBean(MyBean.class, () -> new MyBean(secret()));
// after: plain @Bean method Spring can AOT-process
@Configuration
class Cfg {
@Bean MyBean myBean() { return new MyBean(secret()); }
} Defensive patterns
Strategy: validation
Validate before calling
// Fail fast if a bean has an instance supplier and AOT is enabled
RootBeanDefinition mbd = (RootBeanDefinition) registeredBean.getMergedBeanDefinition();
if (mbd.getInstanceSupplier() != null) {
throw new IllegalStateException(
"Bean '" + registeredBean.getBeanName() + "' uses an instance supplier; AOT is not possible.");
} Type guard
// True if the bean definition is AOT-compatible boolean aotCompatible = mbd.getInstanceSupplier() == null;
Prevention
- Avoid context.registerBean(Class, Supplier) when targeting native image.
- Prefer declarative @Bean/@Configuration factory methods.
- Audit BeanFactoryPostProcessors that assign instance suppliers.
- Upgrade Spring Boot to a version whose auto-configurations are AOT-clean.
When it happens
Trigger: A bean definition has been given an InstanceSupplier via setInstanceSupplier(...), and AOT processing reaches getTarget(registeredBean) (e.g. to determine the generated target class for the bean registration). Triggered on beans that were registered with a programmatic supplier rather than a resolvable constructor or factory method.
Common situations: Calling context.registerBean(MyBean.class, () -> ...) or setInstanceSupplier(...) and then running AOT/native-image; Spring Boot auto-configuration in a version that registers an instance supplier; migrating a context to native without refactoring dynamic registrations; testing utilities that supply instances programmatically.
Related errors
- failed to generate code for bean definition
- Failed to instantiate method
- Failed to load Class [
- Unsatisfied dependency expressed through injection point
- Argument type mismatch: expected '
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/e0a49ff020f2e255.
Report an issue: GitHub.
Appendix: source
Thrown at spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java:82
private final Supplier<InstantiationDescriptor> instantiationDescriptor;
DefaultBeanRegistrationCodeFragments(
BeanRegistrationsCode beanRegistrationsCode, RegisteredBean registeredBean,
BeanDefinitionMethodGeneratorFactory beanDefinitionMethodGeneratorFactory) {
this.beanRegistrationsCode = beanRegistrationsCode;
this.registeredBean = registeredBean;
this.beanDefinitionMethodGeneratorFactory = beanDefinitionMethodGeneratorFactory;
this.instantiationDescriptor = SingletonSupplier.of(registeredBean::resolveInstantiationDescriptor);
}
@Override
public ClassName getTarget(RegisteredBean registeredBean) {
if (hasInstanceSupplier()) {
throw new AotBeanProcessingException(registeredBean, "instance supplier is not supported");
}
Class<?> target = extractDeclaringClass(registeredBean, this.instantiationDescriptor.get());
while (target.getName().startsWith("java.") && registeredBean.isInnerBean()) {
RegisteredBean parent = registeredBean.getParent();
Assert.state(parent != null, "No parent available for inner bean");
target = parent.getBeanClass();
}
return (target.isArray() ? ClassName.get(target.getComponentType()) : ClassName.get(target));
}
private Class<?> extractDeclaringClass(RegisteredBean registeredBean, InstantiationDescriptor instantiationDescriptor) {
Class<?> declaringClass = ClassUtils.getUserClass(instantiationDescriptor.targetClass());
if (instantiationDescriptor.executable() instanceof Constructor<?> ctor &&
AccessControl.forMember(ctor).isPublic() && FactoryBean.class.isAssignableFrom(declaringClass)) {
return extractTargetClassFromFactoryBean(declaringClass, registeredBean.getBeanType());
}
return declaringClass;
}View on GitHub (pinned to 69bf83ad71)