spring-projects/spring-framework · error · UnsatisfiedDependencyException

Unsatisfied dependency expressed through

Error message

Unsatisfied dependency expressed through {}

What it means

Thrown as UnsatisfiedDependencyException from AutowiredFieldElement.resolveFieldValue() when beanFactory.resolveDependency() throws a BeansException for an @Autowired field. The exception captures the InjectionPoint (the field) so the user sees which field caused the failure. Common underlying causes are NoSuchBeanDefinitionException or NoUniqueBeanDefinitionException.

Solutions

  1. Check the nested cause — if NoSuchBeanDefinitionException, register a bean of the required type or mark the field @Autowired(required=false).
  2. If NoUniqueBeanDefinitionException, add @Qualifier("beanName") or designate one implementation @Primary.
  3. Verify @ComponentScan covers the package containing the implementation.

Example fix

// before
@Autowired
private MyRepository repo; // two implementations exist

// after
@Autowired
@Qualifier("jpaRepository")
private MyRepository repo;
Defensive patterns

Strategy: try-catch

Validate before calling

// Before context refresh, verify beans exist for each @Autowired field type
for (Field f : MyBean.class.getDeclaredFields()) {
    if (f.isAnnotationPresent(Autowired.class)) {
        String[] names = beanFactory.getBeanNamesForType(f.getType());
        if (names.length == 0 && f.getAnnotation(Autowired.class).required()) {
            System.err.println("Missing bean for field: " + f.getName());
        }
        if (names.length > 1 && !f.isAnnotationPresent(Qualifier.class)) {
            System.err.println("Ambiguous bean for field: " + f.getName());
        }
    }
}

Try / catch

try {
    context.getBean(MyBean.class);
} catch (UnsatisfiedDependencyException ex) {
    InjectionPoint ip = ex.getInjectionPoint();
    if (ip != null) {
        System.err.println("Failed at field/method: " + ip.getMember());
    }
    Throwable cause = ex.getCause(); // NoSuchBeanDefinitionException etc.
}

Prevention

When it happens

Trigger: An @Autowired field's type cannot be resolved: no bean of that type exists, multiple beans exist without a disambiguating @Qualifier, or a scoped proxy resolution fails. The catch at line 766-768 wraps the BeansException into UnsatisfiedDependencyException referencing the field.

Common situations: Declaring @Autowired on an interface with no implementations registered. Forgetting to register a @Component via @ComponentScan. Multiple implementations of an interface without @Primary or @Qualifier. A required bean failing its own creation (cascading failure).

Related errors


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

Appendix: source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java:767

			}
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}

		private @Nullable Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
			DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
			desc.setContainingClass(bean.getClass());
			Set<String> autowiredBeanNames = new LinkedHashSet<>(2);
			Assert.state(beanFactory != null, "No BeanFactory available");
			TypeConverter typeConverter = beanFactory.getTypeConverter();
			Object value;
			try {
				value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
			}
			catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
			}
			synchronized (this) {
				if (!this.cached) {
					if (value != null || this.required) {
						Object cachedFieldValue = desc;
						registerDependentBeans(beanName, autowiredBeanNames);
						if (value != null && autowiredBeanNames.size() == 1) {
							String autowiredBeanName = autowiredBeanNames.iterator().next();
							if (beanFactory.containsBean(autowiredBeanName) &&
									beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
								cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
							}
						}
						this.cachedFieldValue = cachedFieldValue;
						this.cached = true;
					}
					else {
						this.cachedFieldValue = null;

View on GitHub (pinned to 69bf83ad71)