chinabugotech/hutool · error · IllegalArgumentException

No constructor provided

Error message

No constructor provided

What it means

Thrown by CglibProxyFactory.create only when the target class exposes zero constructors to ReflectUtil.getConstructors AND no IllegalArgumentException was captured during iteration. In the normal failure case (all constructors rejected by enhancer.create) the LAST IllegalArgumentException is rethrown instead, so this literal message specifically indicates an empty constructor set -- i.e. the target is not a normal instantiable class (array, interface, primitive, or a synthetic type with no declared constructors).

Source

Thrown at hutool-aop/src/main/java/cn/hutool/aop/proxy/CglibProxyFactory.java:61

		Class<?>[] parameterTypes;
		Object[] values;
		IllegalArgumentException finalException = null;
		for (final Constructor<?> constructor : constructors) {
			parameterTypes = constructor.getParameterTypes();
			values = ClassUtil.getDefaultValues(parameterTypes);

			try {
				return (T) enhancer.create(parameterTypes, values);
			} catch (final IllegalArgumentException e) {
				//ignore
				finalException = e;
			}
		}
		if (null != finalException) {
			throw finalException;
		}

		throw new IllegalArgumentException("No constructor provided");
	}
}

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Ensure the target is a concrete, non-final class with at least one constructor.
  2. For interfaces, use a JDK dynamic proxy (ProxyUtil / Proxy.newProxyInstance) instead of cglib.
  3. Do not proxy arrays, primitives, or synthetic proxy classes.
  4. If the class genuinely has constructors but they are filtered, review ReflectUtil.getConstructors behavior / access rules.

Example fix

// before
SomeInterface proxy = new SimpleAspect<>(someImpl).proxy();
// or passing an array / interface -> No constructor provided

// after -- proxy a concrete class with cglib, or use JDK proxy for interfaces
ConcreteImpl impl = new ConcreteImpl();
ConcreteImpl proxy = ProxyUtil.proxy(impl, new Aspect() { /*...*/ });
Defensive patterns

Strategy: type-guard

Validate before calling

// Reject non-instantiable targets before proxying
Class<?> c = target.getClass();
if (c.isArray() || c.isInterface() || c.isPrimitive() || c.isEnum()
    || java.lang.reflect.Modifier.isAbstract(c.getModifiers())) {
    throw new IllegalArgumentException("cannot cglib-proxy " + c);
}
if (c.getDeclaredConstructors().length == 0) {
    throw new IllegalArgumentException("no constructors on " + c);
}

Type guard

static boolean isCglibProxyable(Object target) {
    if (target == null) return false;
    Class<?> c = target.getClass();
    return !c.isInterface() && !c.isArray() && !c.isPrimitive()
        && !Modifier.isFinal(c.getModifiers())
        && c.getDeclaredConstructors().length > 0;
}

Try / catch

try {
    return ProxyUtil.proxy(target, aspect);
} catch (IllegalArgumentException e) {
    if ("No constructor provided".equals(e.getMessage())) {
        // target is interface/array/primitive/synthetic -> switch to JDK dynamic proxy
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling SimpleAspect<T>.proxy (or ProxyUtil) on an array type, a primitive wrapper with no accessible constructor, an interface (should use JDK dynamic proxy instead), or a JVM-generated/synthetic class whose getDeclaredConstructors returns nothing. Also reachable if ReflectUtil.getConstructors filters out all constructors of the target.

Common situations: Accidentally proxying a Class object, an array, or an interface instead of a concrete class; passing a lambda/synthetic proxy; reflective environments that hide constructors.

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/f78d108dd27bd00c. Report an issue: GitHub.