spring-projects/spring-framework · error · UnsatisfiedDependencyException

Unsatisfied dependency expressed through injection point

Error message

Unsatisfied dependency expressed through injection point

What it means

Thrown as an UnsatisfiedDependencyException when the AOT BeanInstanceSupplier cannot resolve an autowired argument of the bean's constructor or factory method. In resolveAutowiredArgument, the supplier delegates to RegisteredBean.resolveAutowiredArgument; if that throws a BeansException (no candidate, ambiguous, conversion failure), it is wrapped with the bean name and the DependencyDescriptor so the failing injection point is visible.

Source

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

		ValueHolder resolvedHolder = new ValueHolder(value, valueHolder.getType(), valueHolder.getName());
		resolvedHolder.setSource(valueHolder);
		return resolvedHolder;
	}

	private @Nullable Object resolveAutowiredArgument(RegisteredBean registeredBean, DependencyDescriptor descriptor,
			@Nullable ValueHolder argumentValue, Set<String> autowiredBeanNames) {

		TypeConverter typeConverter = registeredBean.getBeanFactory().getTypeConverter();
		if (argumentValue != null) {
			return (argumentValue.isConverted() ? argumentValue.getConvertedValue() :
					typeConverter.convertIfNecessary(argumentValue.getValue(),
							descriptor.getDependencyType(), descriptor.getMethodParameter()));
		}
		try {
			return registeredBean.resolveAutowiredArgument(descriptor, typeConverter, autowiredBeanNames);
		}
		catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(null, registeredBean.getBeanName(), descriptor, ex);
		}
	}

	private Object instantiate(RegisteredBean registeredBean, Executable executable, @Nullable Object[] args) {
		if (executable instanceof Constructor<?> constructor) {
			if (registeredBean.getBeanFactory() instanceof DefaultListableBeanFactory dlbf &&
					registeredBean.getMergedBeanDefinition().hasMethodOverrides()) {
				return dlbf.getInstantiationStrategy().instantiate(registeredBean.getMergedBeanDefinition(),
						registeredBean.getBeanName(), registeredBean.getBeanFactory());
			}
			return BeanUtils.instantiateClass(constructor, args);
		}
		if (executable instanceof Method method) {
			Object target = null;
			String factoryBeanName = registeredBean.getMergedBeanDefinition().getFactoryBeanName();
			if (factoryBeanName != null) {
				target = registeredBean.getBeanFactory().getBean(factoryBeanName, method.getDeclaringClass());
			}

View on GitHub (pinned to 69bf83ad71)

Solutions

  1. Look at the DependencyDescriptor in the exception to find the constructor/factory-method parameter that failed, then register or qualify a bean of that type.
  2. Add @Qualifier or @Primary to disambiguate when multiple candidates of the parameter type exist.
  3. Verify @Value placeholders resolve and that a PropertySourcesPlaceholderConfigurer/Environment is present in the native image.
  4. If the parameter is optional, make it Optional<T>, ObjectProvider<T>, or mark @Autowired(required=false) as appropriate for the injection point.
  5. Regenerate AOT artifacts (clean native build) after changing the bean class to avoid stale metadata.

Example fix

// before: constructor needs a missing collaborator -> UnsatisfiedDependencyException
public OrderService(PaymentGateway gateway) { ... }

// after: register the bean and disambiguate
@Bean
@Primary
public PaymentGateway stripeGateway() { ... }
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check that constructor/factory-method arguments are resolvable
for (Class<?> pt : executable.getParameterTypes()) {
    if (bf.getBeanNamesForType(pt).length == 0 && !isOptional(pt)) {
        throw new IllegalStateException("Missing bean for constructor arg: " + pt);
    }
}

Try / catch

try {
    return instanceSupplier.get(registeredBean);
} catch (UnsatisfiedDependencyException ex) {
    throw new ConfigurationException("Cannot instantiate " + registeredBean.getBeanName(), ex);
}

Prevention

When it happens

Trigger: Invoking a generated BeanInstanceSupplier whose underlying constructor/factory method has arguments that beanFactory.resolveDependency cannot satisfy at runtime. Common when an autowired constructor parameter has no qualifying bean, multiple candidates without @Primary/@Qualifier, or an unconvertible value.

Common situations: Bean instantiated by AOT supplier whose constructor needs a collaborator that was not registered in the trimmed native-image context; constructor-injected @Value with an unresolved placeholder; multiple DataSource/RestTemplate-style beans with no disambiguation; bean class changed signature in a new version but the AOT metadata is stale.

Related errors


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