spring-projects/spring-ai · error · IllegalArgumentException

Impossible to resolve the type of bean

Error message

Impossible to resolve the type of bean 

What it means

Thrown when resolving a component bean's type fails because the bean's declared class name cannot be loaded from the context's class loader (ClassNotFoundException). Spring cannot determine the bean's Java type, which is required for tool type inference.

Source

Thrown at spring-ai-model/src/main/java/org/springframework/ai/tool/resolution/TypeResolverHelper.java:208

				else if (isParamMismatch(uniqueCandidate, candidate)) {
					uniqueCandidate = null;
					break;
				}
			}
		}

		return uniqueCandidate;
	}

	private static ResolvableType resolveComponentBeanType(GenericApplicationContext applicationContext,
			BeanDefinition beanDefinition, String beanName) {
		if (beanDefinition.getFactoryMethodName() == null && beanDefinition.getBeanClassName() != null) {
			try {
				return ResolvableType.forClass(
						ClassUtils.forName(beanDefinition.getBeanClassName(), applicationContext.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalArgumentException("Impossible to resolve the type of bean " + beanName, ex);
			}
		}
		throw new IllegalArgumentException("Impossible to resolve the type of bean " + beanName);
	}

	static private Method[] getCandidateMethods(Class<?> factoryClass, RootBeanDefinition mbd) {
		return (mbd.isNonPublicAccessAllowed() ? ReflectionUtils.getUniqueDeclaredMethods(factoryClass)
				: factoryClass.getMethods());
	}

	static private boolean isStaticCandidate(Method method, Class<?> factoryClass) {
		return (Modifier.isStatic(method.getModifiers()) && method.getDeclaringClass() == factoryClass);
	}

	static private boolean isParamMismatch(Method uniqueCandidate, Method candidate) {
		int uniqueCandidateParameterCount = uniqueCandidate.getParameterCount();
		int candidateParameterCount = candidate.getParameterCount();
		return (uniqueCandidateParameterCount != candidateParameterCount

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Add the missing class's artifact to the runtime classpath (check dependency scope is not 'provided' or missing at runtime)
  2. Update bean definitions/configuration to reference the class's current fully-qualified name
  3. Verify the class is loadable: Class.forName("com.example.BeanType") in the same classloader
  4. Register the bean via a factory method (@Bean) so type resolution doesn't rely on the class name string

Example fix

// before (beanClassName no longer on classpath)
@Bean(name = "toolBean")  // beanClassName=com.old.Missing
// after — define with explicit factory method so type is resolvable
@Bean
public MyFunction toolBean() { return new MyFunction(); }
Defensive patterns

Strategy: validation

Validate before calling

try {
    ClassUtils.forName(beanDefinition.getBeanClassName(), classLoader);
} catch (ClassNotFoundException e) {
    // fix classpath before enabling tool resolution
}

Try / catch

try { toolResolution(); } catch (IllegalArgumentException e) {
    if (e.getCause() instanceof ClassNotFoundException cnfe) { /* restore missing dependency */ }
}

Prevention

When it happens

Trigger: resolveBeanType encounters a bean definition with no factory method but a beanClassName that fails ClassUtils.forName — e.g. class removed after config was written, dependency not on runtime classpath, class in a different classloader (fat-jar/reload scenarios).

Common situations: Upgrading/downgrading a dependency so a previously referenced class disappears; class referenced only in compile-scope but not runtime scope; hot-reload/devtools classloader mismatches; renaming classes without updating XML/component configuration.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/57fb23b06b4b159f. Report an issue: GitHub.