spring-projects/spring-framework · error · IllegalArgumentException

Cannot create class proxy for TargetSource with null target…

Error message

Cannot create class proxy for TargetSource with null target class

What it means

Thrown by the static helper ProxyFactory.getProxy(TargetSource) when targetSource.getTargetClass() == null. That overload forces proxyTargetClass=true (a CGLIB class proxy), so a concrete target class is mandatory. It fails fast rather than handing a null class to the CGLIB proxy factory.

Solutions

  1. Use a TargetSource that returns a concrete class, e.g. new SingletonTargetSource(myBean) or implement getTargetClass() to return the implementation class.
  2. If you only have an interface, use the overload ProxyFactory.getProxy(Class<T> proxyInterface, TargetSource ts) instead, which builds a JDK proxy.
  3. Construct the ProxyFactory manually with setTargetSource + setInterfaces if you need both behaviors.

Example fix

// before
TargetSource ts = new EmptyTargetSource(null, true);
Object p = ProxyFactory.getProxy(ts); // -> null target class

// after
TargetSource ts = new SingletonTargetSource(new MyServiceImpl());
Object p = ProxyFactory.getProxy(ts);
Defensive patterns

Strategy: validation

Validate before calling

if (targetSource.getTargetClass() == null) {
  throw new IllegalArgumentException("TargetSource " + targetSource + " exposes no target class");
}
Object proxy = ProxyFactory.getProxy(targetSource);

Type guard

static boolean hasConcreteTargetClass(TargetSource ts) { return ts.getTargetClass() != null && !ts.getTargetClass().isInterface(); }

Try / catch

try { return ProxyFactory.getProxy(ts); }
catch (IllegalArgumentException e) {
  if (e.getMessage().contains("null target class")) { /* swap in SingletonTargetSource */ }
  throw e;
}

Prevention

When it happens

Trigger: Calling ProxyFactory.getProxy(targetSource) where the TargetSource has no concrete class: an empty/abstract TargetSource whose getTargetClass() returns null; a custom TargetSource that lazily resolves the class but does not expose it; passing an EmptyTargetSource.

Common situations: Hand-rolled TargetSource for pooling/thread-local that forgot to implement getTargetClass(); passing a TargetSource built for an interface-only proxy into the class-proxy overload; mis-wiring in remoting/scoped-proxy code.

Related errors


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

Appendix: source

Thrown at spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactory.java:161

	 * @param proxyInterface the interface that the proxy should implement
	 * @param targetSource the TargetSource that the proxy should invoke
	 * @return the proxy object
	 * @see #ProxyFactory(Class, org.springframework.aop.TargetSource)
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getProxy(Class<T> proxyInterface, TargetSource targetSource) {
		return (T) new ProxyFactory(proxyInterface, targetSource).getProxy();
	}

	/**
	 * Create a proxy for the specified {@code TargetSource} that extends
	 * the target class of the {@code TargetSource}.
	 * @param targetSource the TargetSource that the proxy should invoke
	 * @return the proxy object
	 */
	public static Object getProxy(TargetSource targetSource) {
		if (targetSource.getTargetClass() == null) {
			throw new IllegalArgumentException("Cannot create class proxy for TargetSource with null target class");
		}
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.setTargetSource(targetSource);
		proxyFactory.setProxyTargetClass(true);
		return proxyFactory.getProxy();
	}

}

View on GitHub (pinned to 69bf83ad71)