spring-projects/spring-framework · error · IllegalArgumentException

%s cannot be found on %s

Error message

%s cannot be found on %s

What it means

Thrown as an IllegalArgumentException when the AOT ConstructorLookup cannot find a declared constructor on the bean class matching the recorded parameter types. The supplier stored the constructor signature at AOT time; at runtime getDeclaredConstructor(parameterTypes) throws NoSuchMethodException, which is wrapped with a message describing the expected parameter types and the target class.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java:407

	/**
	 * Performs lookup of the {@link Constructor}.
	 */
	private static class ConstructorLookup extends ExecutableLookup {

		private final Class<?>[] parameterTypes;

		ConstructorLookup(Class<?>[] parameterTypes) {
			this.parameterTypes = parameterTypes;
		}

		@Override
		public Executable get(RegisteredBean registeredBean) {
			Class<?> beanClass = registeredBean.getMergedBeanDefinition().getBeanClass();
			try {
				return beanClass.getDeclaredConstructor(this.parameterTypes);
			}
			catch (NoSuchMethodException ex) {
				throw new IllegalArgumentException(
						"%s cannot be found on %s".formatted(this, beanClass.getName()), ex);
			}
		}

		@Override
		public String toString() {
			return "Constructor with parameter types [%s]".formatted(toCommaSeparatedNames(this.parameterTypes));
		}
	}


	/**
	 * Performs lookup of the factory {@link Method}.
	 */
	private static class FactoryMethodLookup extends ExecutableLookup {

		private final Class<?> declaringClass;

View on GitHub (pinned to 69bf83ad71)

Solutions

  1. Clean and regenerate AOT/native artifacts so the recorded constructor parameter types match the current bean class.
  2. Confirm the runtime classpath uses the same bean class version as the AOT build (no version drift).
  3. If you intentionally changed the constructor, update @Autowired/@ConstructorBinding and bean definition so Spring resolves to the new constructor.
  4. Add or restore the constructor with the exact parameter types listed in the message.
  5. Run the JVM build first; the same NoSuchMethodException surfaces earlier and points at the class mismatch.

Example fix

// before: AOT recorded constructor (String, int) but class now has (String)
public Service(String name, int id) { ... } // changed to
public Service(String name) { ... }

// after: rebuild AOT metadata and align the constructor
./gradlew clean build   // regenerate native/AOT metadata for Service(String)
Defensive patterns

Strategy: validation

Validate before calling

// Verify the recorded constructor still exists on the bean class
Class<?> beanClass = registeredBean.getBeanClass();
try {
    beanClass.getDeclaredConstructor(recordedParameterTypes);
} catch (NoSuchMethodException ex) {
    throw new IllegalStateException("Stale AOT metadata: constructor missing on " + beanClass, ex);
}

Prevention

When it happens

Trigger: ConstructorLookup.get(registeredBean) calls beanClass.getDeclaredConstructor(parameterTypes) and that exact constructor does not exist. Happens when the bean class was changed (constructor signature altered, removed, made package-private to a different package, or replaced by a factory method) but AOT metadata still references the old signature.

Common situations: Refactoring the bean class constructor after AOT metadata was generated; introducing a different Spring version that picks a different constructor; bean class loaded from a different artifact version at runtime than at build time; class with multiple constructors where the intended one was removed; AOT cache not cleaned after a code change.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/31f17855b74d80e6. Report an issue: GitHub.