spring-projects/spring-framework · error · IllegalAccessException

Auto-growing not allowed with private constructor: ${ctor}

Error message

Auto-growing not allowed with private constructor: ${ctor}

What it means

An IllegalAccessException with this message is thrown inside newValue() when auto-growing needs to instantiate a nested bean but its only no-arg constructor is private. Spring explicitly refuses private constructors for auto-grow (unlike BeanUtils.instantiateClass, which would make it accessible). The thrown IllegalAccessException is then caught by the surrounding catch(Throwable) and re-wrapped into a NullValueInNestedPathException (error 143) as the cause.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java:894

	}

	private Object newValue(Class<?> type, @Nullable TypeDescriptor desc, String name) {
		try {
			if (type.isArray()) {
				return createArray(type);
			}
			else if (Collection.class.isAssignableFrom(type)) {
				TypeDescriptor elementDesc = (desc != null ? desc.getElementTypeDescriptor() : null);
				return CollectionFactory.createCollection(type, (elementDesc != null ? elementDesc.getType() : null), 16);
			}
			else if (Map.class.isAssignableFrom(type)) {
				TypeDescriptor keyDesc = (desc != null ? desc.getMapKeyTypeDescriptor() : null);
				return CollectionFactory.createMap(type, (keyDesc != null ? keyDesc.getType() : null), 16);
			}
			else {
				Constructor<?> ctor = type.getDeclaredConstructor();
				if (Modifier.isPrivate(ctor.getModifiers())) {
					throw new IllegalAccessException("Auto-growing not allowed with private constructor: " + ctor);
				}
				return BeanUtils.instantiateClass(ctor);
			}
		}
		catch (Throwable ex) {
			throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + name,
					"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path", ex);
		}
	}

	/**
	 * Create the array for the given array type.
	 * @param arrayType the desired type of the target array
	 * @return a new array instance
	 */
	private static Object createArray(Class<?> arrayType) {
		Assert.notNull(arrayType, "Array type must not be null");
		Class<?> componentType = arrayType.componentType();

View on GitHub (pinned to e8729d0438)

Solutions

  1. Add a non-private (public or package-private) no-arg constructor to the nested type so auto-grow can call it.
  2. Disable auto-grow and pre-initialize the nested field with a properly constructed instance.
  3. Provide a factory method / @Bean and inject the instance instead of relying on Spring to auto-grow it.
  4. If you cannot change the class, wrap it in a holder type whose constructor instantiates the target explicitly.

Example fix

// before
public class Address { private Address() {} public Address(String s) {} }
// auto-grow fails: private no-arg ctor

// after
public class Address { public Address() {} public Address(String s) {} }
Defensive patterns

Strategy: validation

Validate before calling

// Verify the nested type has a non-private no-arg constructor before enabling auto-grow
Class<?> type = wrapper.getPropertyType(propName);
if (type != null) {
  Constructor<?> c = type.getDeclaredConstructor();
  if (Modifier.isPrivate(c.getModifiers())) {
    // do not enable auto-grow; set the value manually
  }
}

Type guard

public static boolean hasAutoGrowFriendlyCtor(Class<?> type) {
  try {
    Constructor<?> c = type.getDeclaredConstructor();
    return !Modifier.isPrivate(c.getModifiers());
  } catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
  wrapper.setAutoGrowNestedPaths(true);
  wrapper.setPropertyValue(path, value);
} catch (NullValueInNestedPathException e) {
  Throwable cause = e.getCause();
  if (cause instanceof IllegalAccessException) { /* private ctor: init manually */ }
}

Prevention

When it happens

Trigger: autoGrowNestedPaths=true, nested property value is null, the property type has a private no-arg constructor (common with singletons, builders, or classes designed with only a public arg-taking constructor plus a private default). Reached via AbstractNestablePropertyAccessor.java:892-895.

Common situations: Auto-growing into a singleton-style type, a class with only public MyType(String)/private MyType(), or a nested type from a third-party library that hides its default constructor. Config binding into such a type.

Related errors


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