spring-projects/spring-framework · error · IllegalArgumentException

[{}] is not an interface

Error message

[{}] is not an interface

What it means

Thrown by AdvisedSupport.addInterface when the supplied Class is not actually a Java interface (!ifc.isInterface()). JDK dynamic proxies can only implement interfaces, so Spring rejects any concrete class or enum passed as a proxied interface to keep the advisor model consistent. This is a hard validation enforced at configuration time.

Source

Thrown at spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java:234

	/**
	 * Set the interfaces to be proxied.
	 */
	public void setInterfaces(Class<?>... interfaces) {
		Assert.notNull(interfaces, "Interfaces must not be null");
		this.interfaces.clear();
		for (Class<?> ifc : interfaces) {
			addInterface(ifc);
		}
	}

	/**
	 * Add a new proxied interface.
	 * @param ifc the additional interface to proxy
	 */
	public void addInterface(Class<?> ifc) {
		Assert.notNull(ifc, "Interface must not be null");
		if (!ifc.isInterface()) {
			throw new IllegalArgumentException("[" + ifc.getName() + "] is not an interface");
		}
		if (!this.interfaces.contains(ifc)) {
			this.interfaces.add(ifc);
			adviceChanged();
		}
	}

	/**
	 * Remove a proxied interface.
	 * <p>Does nothing if the given interface isn't proxied.
	 * @param ifc the interface to remove from the proxy
	 * @return {@code true} if the interface was removed; {@code false}
	 * if the interface was not found and hence could not be removed
	 */
	public boolean removeInterface(Class<?> ifc) {
		return this.interfaces.remove(ifc);
	}

View on GitHub (pinned to e8729d0438)

Solutions

  1. Pass only interface types to addInterface/setInterfaces; extract or identify the interface the target implements (e.g. MyService instead of MyServiceImpl).
  2. If you really need to proxy a concrete class, enable proxyTargetClass=true (CGLIB) rather than adding the class as an interface.
  3. Add an isInterface() guard in any generic helper that builds the interface array.

Example fix

// before
proxyFactory.setInterfaces(MyServiceImpl.class);  // concrete class

// after
proxyFactory.setInterfaces(MyService.class);  // the interface
// or, to proxy the concrete class itself:
proxyFactory.setProxyTargetClass(true);
proxyFactory.setTarget(new MyServiceImpl());
Defensive patterns

Strategy: validation

Validate before calling

Class<?> ifc = MyServiceImpl.class;
if (!ifc.isInterface()) {
  throw new IllegalArgumentException(
    ifc.getName() + " is not an interface; pass an interface or enable proxyTargetClass");
}

Type guard

static boolean isProxiableInterface(Class<?> c) {
  return c != null && c.isInterface();
}

Prevention

When it happens

Trigger: Calling proxyFactory.addInterface(MyConcreteClass.class) or advised.setInterfaces(SomeClass.class) where the argument is a class rather than an interface; using proxyTargetClass=false (JDK proxy mode) but adding a concrete class to the interface list; programmatic AspectJ-style wiring mistakes.

Common situations: Confusing the target class (which can be concrete) with proxied interfaces; accidentally passing an abstract class; generic helper code that passes arbitrary Class<?> without checking isInterface(); migrating from CGLIB to JDK proxy without converting the interface list.

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/b9fadff730a3d9a3.json. Report an issue: GitHub.