spring-projects/spring-security · error · IllegalStateException

Failed to resolve an unique bean (single or primary) of type

Error message

Failed to resolve an unique bean (single or primary) of type [{object.getClass()}] from the BeanFactory.
Because the object is a CGLIB Proxy, a raw bean cannot be initialized during runtime in a native image.

What it means

In a GraalVM native image, initializeBeanIfNeeded cannot resolve/initialize a raw bean for a CGLIB proxy object; when the BeanFactory lookup returns null it throws IllegalStateException with a message naming the unresolved type. Native images forbid creating/initializing raw beans at runtime for proxied types because the necessary reflective metadata is absent.

Solutions

  1. Avoid passing CGLIB-proxied objects through ObjectPostProcessor in native images; post-process the underlying instance or disable proxying where possible.
  2. Register native/AOT hints (RuntimeHints) for the affected classes so bean resolution works in the image.
  3. Ensure exactly one primary/single bean of the required type exists, or qualify the bean explicitly.
  4. Prefer JDK dynamic proxies (proxyTargetClass=false) or restructure config so the object is not proxied before initialization.

Example fix

// before
http.objectPostProcessor.postProcess(proxiedConfigurer); // fails in native image
// after
http.objectPostProcessor.postProcess(new MyConfigurer()); // raw instance, no CGLIB proxy
Defensive patterns

Strategy: try-catch

Validate before calling

// before post-processing in native image
if (SpringFactoriesUtils // or AOT check
        .isNativeImage() && AopUtils.isCglibProxy(object)) {
    throw new IllegalStateException("Cannot postProcess CGLIB proxy " + object.getClass() + " in native image");
}

Type guard

static boolean isCglibProxy(Object o) {
    return o != null && org.springframework.aop.support.AopUtils.isCglibProxy(o);
}

Try / catch

try {
    processed = objectPostProcessor.postProcess(object);
} catch (IllegalStateException e) {
    if (e.getMessage().contains("CGLIB Proxy")) {
        // rebuild with the raw (unproxied) instance or register native hints
        processed = objectPostProcessor.postProcess(AopProxyUtils.getSingletonTarget(object));
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Running a Spring Security configuration in a native image where an object passed to postProcess is a CGLIB proxy (e.g. @Configuration- or @Transactional-proxied classes) and initializeBeanIfNeeded does a getBean of that type which fails to find a unique single/primary bean.

Common situations: Spring Boot native (AOT) builds with security configurers post-processing proxied beans; multiple beans of the same type so no unique candidate resolves; missing native hints for custom configurer classes.

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/8581935dc26ea622. Report an issue: GitHub.

Appendix: source

Thrown at config/src/main/java/org/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.java:108

	 * the application is a native image
	 * @see <a href=
	 * "https://github.com/spring-projects/spring-security/issues/14825">Issue
	 * gh-14825</a>
	 */
	@SuppressWarnings("unchecked")
	private <T> T initializeBeanIfNeeded(T object) {
		if (!NativeDetector.inNativeImage() || !AopUtils.isCglibProxy(object)) {
			return (T) this.autowireBeanFactory.initializeBean(object, object.toString());
		}
		ObjectProvider<?> provider = this.autowireBeanFactory.getBeanProvider(object.getClass());
		Object bean = provider.getIfUnique();
		if (bean == null) {
			String msg = """
					Failed to resolve an unique bean (single or primary) of type [%s] from the BeanFactory.
					Because the object is a CGLIB Proxy, a raw bean cannot be initialized during runtime in a native image.
					"""
				.formatted(object.getClass());
			throw new IllegalStateException(msg);
		}
		return (T) bean;
	}

	@Override
	public void afterSingletonsInstantiated() {
		for (SmartInitializingSingleton singleton : this.smartSingletons) {
			singleton.afterSingletonsInstantiated();
		}
	}

	@Override
	public void destroy() {
		for (DisposableBean disposable : this.disposableBeans) {
			try {
				disposable.destroy();
			}
			catch (Exception ex) {

View on GitHub (pinned to 96852e8860)