spring-projects/spring-framework · error · IllegalArgumentException

Both 'constructorArgs' and 'constructorArgTypes' need to be

Error message

Both 'constructorArgs' and 'constructorArgTypes' need to be specified

What it means

Thrown by CglibAopProxy.setConstructorArguments when exactly one of constructorArgs / constructorArgTypes is null. To instantiate the CGLIB proxy subclass via a parameterized constructor, CGLIB needs both the argument values and their corresponding types; passing one without the other is ambiguous. Spring rejects the half-specified state immediately.

Source

Thrown at spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java:148

	 * Create a new CglibAopProxy for the given AOP configuration.
	 * @param config the AOP configuration as AdvisedSupport object
	 * @throws AopConfigException if the config is invalid. We try to throw an informative
	 * exception in this case, rather than let a mysterious failure happen later.
	 */
	public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		this.advised = config;
		this.advisedDispatcher = new AdvisedDispatcher(this.advised);
	}

	/**
	 * Set constructor arguments to use for creating the proxy.
	 * @param constructorArgs the constructor argument values
	 * @param constructorArgTypes the constructor argument types
	 */
	public void setConstructorArguments(Object @Nullable [] constructorArgs, Class<?> @Nullable [] constructorArgTypes) {
		if (constructorArgs == null || constructorArgTypes == null) {
			throw new IllegalArgumentException("Both 'constructorArgs' and 'constructorArgTypes' need to be specified");
		}
		if (constructorArgs.length != constructorArgTypes.length) {
			throw new IllegalArgumentException("Number of 'constructorArgs' (" + constructorArgs.length +
					") must match number of 'constructorArgTypes' (" + constructorArgTypes.length + ")");
		}
		this.constructorArgs = constructorArgs;
		this.constructorArgTypes = constructorArgTypes;
	}


	@Override
	public Object getProxy() {
		return buildProxy(null, false);
	}

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		return buildProxy(classLoader, false);

View on GitHub (pinned to e8729d0438)

Solutions

  1. Supply both arrays: setConstructorArguments(new Object[]{...}, new Class<?>[]{...}) with matching, non-null values.
  2. If the target class has a no-arg constructor, omit setConstructorArguments entirely (the default path uses enhancer.create()).
  3. Ensure the calling code populates both arrays from the same source of truth so neither stays null.

Example fix

// before
cglibProxy.setConstructorArguments(new Object[]{42L, "x"}, null);  // types missing

// after
cglibProxy.setConstructorArguments(
  new Object[]{42L, "x"},
  new Class<?>[]{long.class, String.class});
Defensive patterns

Strategy: validation

Validate before calling

if (constructorArgs == null || constructorArgTypes == null) {
  throw new IllegalArgumentException("Both constructorArgs and constructorArgTypes must be non-null");
}

Prevention

When it happens

Trigger: Programmatically calling cglibProxy.setConstructorArguments(args, null) or (null, types); building a CGLIB proxy for a class with no no-arg constructor and supplying only values or only types; reflective wiring that drops one array.

Common situations: Custom ProxyFactory usage targeting a class whose only constructor takes arguments; integrating with a factory that constructs proxies with specific ctor args; forgetting to populate the second array in a builder pattern.

Related errors


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