spring-projects/spring-framework · error · FactoryBeanNotInitializedException

does not support circular references

Error message

 does not support circular references

What it means

Thrown as a FactoryBeanNotInitializedException when a singleton-scoped FactoryBean is asked for its bean before it has finished initializing AND it does not opt in to early-proxy exposure. AbstractFactoryBean.getEarlySingletonInstance calls getEarlySingletonInterfaces(); if that returns null (the default), the FactoryBean declares it cannot resolve circular references and throws. Subclasses expose early-singleton interfaces to opt in to circular-reference resolution.

Solutions

  1. Break the circular dependency: inject one side lazily (@Lazy), use setter injection on one leg, or redesign so the FactoryBean does not depend on beans that depend on its product.
  2. If early exposure is acceptable, override getEarlySingletonInterfaces() in the FactoryBean to return the interfaces that the early proxy should expose.
  3. Disable circular references application-wide (spring.main.allow-circular-references=false) to surface such designs at startup as a deliberate error rather than a per-FactoryBean failure.
  4. Refactor the FactoryBean to a plain @Bean method so the container handles the singleton lifecycle and circular reference resolution.
  5. Move the cycle-breaking collaborator into an ObjectProvider<T> or Optional<T> so it is resolved on demand, not during initialization.

Example fix

// before: FactoryBean in a cycle, no early-singleton interfaces
public class MyFactoryBean extends AbstractFactoryBean<MyType> {
    @Override protected MyType createInstance() { return new MyType(collab); }
    // collab depends on MyType -> cycle
}

// after: opt in to early exposure via interfaces
@Override
protected Class<?>[] getEarlySingletonInterfaces() {
    return new Class<?>[] { MyType.class };
}
Defensive patterns

Strategy: validation

Validate before calling

// Detect a FactoryBean in a cycle that cannot break early
AbstractFactoryBean<?> fb = (AbstractFactoryBean<?>) factoryBean;
if (inCycle && fb.getEarlySingletonInterfaces() == null) {
    throw new IllegalStateException(fb.getClass().getName() + " cannot participate in a circular reference");
}

Type guard

// True if the FactoryBean opts in to early circular-reference resolution
boolean supportsCycle = ((AbstractFactoryBean<?>) fb).getEarlySingletonInterfaces() != null;

Prevention

When it happens

Trigger: A circular bean dependency where one of the beans in the cycle is a FactoryBean that has not overridden getEarlySingletonInterfaces() to return a non-null interface array, and Spring tries to obtain an early singleton reference to it to break the cycle. getObject() is invoked during the cycle before the FactoryBean's afterPropertiesSet has populated singletonInstance.

Common situations: Two beans mutually referencing each other where one is an AbstractFactoryBean subclass (e.g. a custom FactoryBean<Object>); spring.main.allow-circular-references=true left on while a FactoryBean in the cycle never declared early-singleton interfaces; upgrading Spring where circular reference handling was tightened; a FactoryBean whose createInstance depends (directly/indirectly) on a bean that depends back on the FactoryBean's product.

Related errors


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

Appendix: source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/config/AbstractFactoryBean.java:164

	public final T getObject() throws Exception {
		if (isSingleton()) {
			T instance = this.singletonInstance;
			return (instance != null ? instance : getEarlySingletonInstance());
		}
		else {
			return createInstance();
		}
	}

	/**
	 * Determine an 'early singleton' instance, exposed in case of a
	 * circular reference. Not called in a non-circular scenario.
	 */
	@SuppressWarnings("unchecked")
	private T getEarlySingletonInstance() {
		Class<?>[] ifcs = getEarlySingletonInterfaces();
		if (ifcs == null) {
			throw new FactoryBeanNotInitializedException(
					getClass().getName() + " does not support circular references");
		}
		if (this.earlySingletonInstance == null) {
			this.earlySingletonInstance = (T) Proxy.newProxyInstance(
					this.beanClassLoader, ifcs, new EarlySingletonInvocationHandler());
		}
		return this.earlySingletonInstance;
	}

	/**
	 * Expose the singleton instance (for access through the 'early singleton' proxy).
	 * @return the singleton instance that this FactoryBean holds
	 * @throws IllegalStateException if the singleton instance is not initialized
	 */
	private T getSingletonInstance() throws IllegalStateException {
		T instance = this.singletonInstance;
		Assert.state(instance != null, "Singleton instance not initialized yet");
		return instance;

View on GitHub (pinned to 69bf83ad71)