spring-projects/spring-framework · error · IllegalArgumentException

Number of 'constructorArgs' ({constructorArgs.length}) must

Error message

Number of 'constructorArgs' ({constructorArgs.length}) must match number of 'constructorArgTypes' ({constructorArgTypes.length})

What it means

Thrown by CglibAopProxy.setConstructorArguments when constructorArgs.length != constructorArgTypes.length. CGLIB resolves the constructor by matching the type array against declared constructors and then passes the value array positionally, so the two arrays must be equal in length. A length mismatch indicates a wiring bug and would otherwise surface as a confusing CGLIB failure.

Source

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

	 * 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);
	}

	@Override

View on GitHub (pinned to e8729d0438)

Solutions

  1. Build both arrays from a single paired list (e.g. List<Pair<Class<?>,Object>>) so they cannot diverge.
  2. Add an assertion args.length == types.length before calling setConstructorArguments.
  3. Log both lengths when the error appears to quickly locate the divergent source.

Example fix

// before
cglibProxy.setConstructorArguments(
  new Object[]{1, "a", true},          // 3
  new Class<?>[]{int.class, String.class}); // 2 -> throws

// after
cglibProxy.setConstructorArguments(
  new Object[]{1, "a", true},
  new Class<?>[]{int.class, String.class, boolean.class});
Defensive patterns

Strategy: validation

Validate before calling

if (constructorArgs.length != constructorArgTypes.length) {
  throw new IllegalArgumentException("args.length=" + constructorArgs.length
    + " types.length=" + constructorArgTypes.length);
}

Prevention

When it happens

Trigger: Calling setConstructorArguments with arrays of different lengths; mutating one array after the other was built; off-by-one in loops that build the two arrays separately.

Common situations: Builder/helper code that assembles args and types from separate collections; copy-paste where values were updated but types were not; varargs confusion.

Related errors


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