spring-projects/spring-framework · error · UnsatisfiedDependencyException

Unsatisfied dependency expressed through parameter

Error message

Unsatisfied dependency expressed through parameter

What it means

Thrown as an UnsatisfiedDependencyException when an @Autowired method (e.g. a setter or arbitrary method) cannot have one of its arguments resolved by the BeanFactory in an AOT-processed application. AutowiredMethodArgumentsResolver iterates the method's parameters, builds a DependencyDescriptor for each, and calls resolveDependency; any BeansException is wrapped with an InjectionPoint(MethodParameter) indicating the offending parameter. It is the AOT counterpart of method injection failures.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredMethodArgumentsResolver.java:185

		TypeConverter typeConverter = beanFactory.getTypeConverter();
		for (int i = 0; i < argumentCount; i++) {
			MethodParameter parameter = new MethodParameter(method, i);
			DependencyDescriptor descriptor = new DependencyDescriptor(parameter, this.required);
			descriptor.setContainingClass(beanClass);
			String shortcut = (this.shortcutBeanNames != null ? this.shortcutBeanNames[i] : null);
			if (shortcut != null) {
				descriptor = new ShortcutDependencyDescriptor(descriptor, shortcut);
			}
			try {
				Object argument = autowireCapableBeanFactory.resolveDependency(
						descriptor, beanName, autowiredBeanNames, typeConverter);
				if (argument == null && !this.required) {
					return null;
				}
				arguments[i] = argument;
			}
			catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(parameter), ex);
			}
		}
		registerDependentBeans(beanFactory, beanName, autowiredBeanNames);
		return AutowiredArguments.of(arguments);
	}

	private Method getMethod(RegisteredBean registeredBean) {
		Method method = ReflectionUtils.findMethod(registeredBean.getBeanClass(),
				this.methodName, this.parameterTypes);
		Assert.notNull(method, () ->
				"Method '%s' with parameter types [%s] declared on %s could not be found.".formatted(
						this.methodName, toCommaSeparatedNames(this.parameterTypes),
						registeredBean.getBeanClass().getName()));
		return method;
	}

	private String toCommaSeparatedNames(Class<?>... parameterTypes) {
		return Arrays.stream(parameterTypes).map(Class::getName)

View on GitHub (pinned to 69bf83ad71)

Solutions

  1. Inspect the InjectionPoint in the exception to find the failing method and parameter index, then ensure exactly one qualifying bean is available.
  2. If the parameter is optional, build the resolver without 'required' semantics so a null argument short-circuits the method call instead of failing.
  3. Add @Qualifier to the parameter or use withShortcut(beanNames) to pin each argument to a specific bean name.
  4. Register the missing bean, or expose it as @Primary if multiple candidates exist and one should win.
  5. Confirm type conversion is possible for @Value parameters and that placeholders resolve in the environment.

Example fix

// before: required method injection failing on missing collaborator
resolver.resolveAndSet(registeredBean, instance); // throws on param 0

// after: pin the ambiguous argument to a named bean
resolver.withShortcut("redisTemplate").resolveAndSet(registeredBean, instance);
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify each method-parameter type is resolvable before resolving
ConfigurableListableBeanFactory bf = registeredBean.getBeanFactory();
for (Class<?> pt : method.getParameterTypes()) {
    String[] names = bf.getBeanNamesForType(pt);
    if (names.length == 0 && required) {
        throw new IllegalStateException("No bean of type " + pt + " for " + method);
    }
}

Try / catch

try {
    resolver.resolveAndSet(registeredBean, instance);
} catch (UnsatisfiedDependencyException ex) {
    InjectionPoint ip = ex.getInjectionPoint();
    MethodParameter mp = (ip != null) ? ip.getMethodParameter() : null;
    throw new ConfigurationException("Cannot wire method param " + mp, ex);
}

Prevention

When it happens

Trigger: Calling resolveAndSet/resolveArguments on an AutowiredMethodArgumentsResolver where at least one MethodParameter's resolveDependency call throws. Triggers when a required parameter type is missing, ambiguous without a qualifier, or unconvertible; argument resolution is skipped (returns null) only if the resolver was built for non-required injection.

Common situations: Setter/method injection where a collaborator bean was removed from the native-image subset; @Autowired on a method whose parameter uses a generic collection type not exposed as a bean; mismatched qualifier on a method parameter; bean renamed or its primary status dropped so multiple candidates now collide.

Related errors


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