spring-projects/spring-framework · error · IllegalStateException

Cannot invoke instance method without factoryBeanName:

Error message

Cannot invoke instance method without factoryBeanName: 

What it means

Thrown as an IllegalStateException when the BeanInstanceSupplier is told to invoke a factory method that is non-static, but the bean definition has no factoryBeanName set. Without a factoryBeanName the supplier has no bean to obtain as the invocation target, so it refuses rather than NPE on method.invoke(null, args).

Solutions

  1. Set the factoryBeanName on the bean definition: definition.setFactoryBeanName("myFactory"); so the supplier can resolve the target bean.
  2. If the factory method should not need an instance, mark it static so the supplier can invoke it without a target.
  3. Regenerate AOT artifacts after changing a @Bean method between static and instance forms so the metadata matches the code.
  4. Validate the bean definition programmatically (factoryBeanName != null XOR Modifier.isStatic(factoryMethod)) before publishing it.

Example fix

// before: instance factory method without a factoryBeanName
RootBeanDefinition bd = new RootBeanDefinition(MyBean.class);
bd.setFactoryMethodName("create"); // create() is non-static

// after: provide the factory bean name
bd.setFactoryBeanName("myFactory");
bd.setFactoryMethodName("create");
Defensive patterns

Strategy: validation

Validate before calling

// Validate factory-method metadata before publishing a bean definition
RootBeanDefinition bd = (RootBeanDefinition) beanDefinition;
Method fm = /* resolved factory method */;
if (!Modifier.isStatic(fm.getModifiers()) && bd.getFactoryBeanName() == null) {
    throw new IllegalStateException("Instance factory method requires factoryBeanName: " + fm);
}

Type guard

// True if the bean definition can be invoked without an instance target
boolean canInvoke = Modifier.isStatic(method.getModifiers()) || factoryBeanName != null;

Prevention

When it happens

Trigger: The instantiation descriptor select a java.lang.reflect.Method that is an instance method (not static), but RootBeanDefinition.getFactoryBeanName() returns null. Triggered in BeanInstanceSupplier.instantiate when building the bean instance via reflection at runtime.

Common situations: Programmatically building a RootBeanDefinition with setFactoryMethodName(name) on an instance method but forgetting setFactoryBeanName(...); a @Bean method that was inadvertently changed from static to instance without updating factory metadata; custom BeanDefinitionRegistryPostProcessor that misconfigures factory method metadata; stale AOT metadata generated against a static factory that later became an instance method.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/9a5f54891b6ca094. Report an issue: GitHub.

Appendix: source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java:361

	}

	private Object instantiate(RegisteredBean registeredBean, Executable executable, @Nullable Object[] args) {
		if (executable instanceof Constructor<?> constructor) {
			if (registeredBean.getBeanFactory() instanceof DefaultListableBeanFactory dlbf &&
					registeredBean.getMergedBeanDefinition().hasMethodOverrides()) {
				return dlbf.getInstantiationStrategy().instantiate(registeredBean.getMergedBeanDefinition(),
						registeredBean.getBeanName(), registeredBean.getBeanFactory());
			}
			return BeanUtils.instantiateClass(constructor, args);
		}
		if (executable instanceof Method method) {
			Object target = null;
			String factoryBeanName = registeredBean.getMergedBeanDefinition().getFactoryBeanName();
			if (factoryBeanName != null) {
				target = registeredBean.getBeanFactory().getBean(factoryBeanName, method.getDeclaringClass());
			}
			else if (!Modifier.isStatic(method.getModifiers())) {
				throw new IllegalStateException("Cannot invoke instance method without factoryBeanName: " + method);
			}
			try {
				ReflectionUtils.makeAccessible(method);
				return method.invoke(target, args);
			}
			catch (Throwable ex) {
				throw new BeanInstantiationException(method, ex.getMessage(), ex);
			}
		}
		throw new IllegalStateException("Unsupported executable " + executable.getClass().getName());
	}


	private static String toCommaSeparatedNames(Class<?>... parameterTypes) {
		return Arrays.stream(parameterTypes).map(Class::getName).collect(Collectors.joining(", "));
	}

View on GitHub (pinned to 69bf83ad71)