{"record":{"id":"4acfa4d1350c62a9","repo":"spring-projects/spring-framework","slug":"unsatisfied-dependency-expressed-through-field","errorCode":null,"errorMessage":"Unsatisfied dependency expressed through field","messagePattern":"Unsatisfied dependency expressed through field","errorType":"exception","errorClass":"UnsatisfiedDependencyException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredFieldValueResolver.java","lineNumber":188,"sourceCode":"\t\tString beanName = registeredBean.getBeanName();\n\t\tClass<?> beanClass = registeredBean.getBeanClass();\n\t\tConfigurableBeanFactory beanFactory = registeredBean.getBeanFactory();\n\t\tDependencyDescriptor descriptor = new DependencyDescriptor(field, this.required);\n\t\tdescriptor.setContainingClass(beanClass);\n\t\tif (this.shortcutBeanName != null) {\n\t\t\tdescriptor = new ShortcutDependencyDescriptor(descriptor, this.shortcutBeanName);\n\t\t}\n\t\tSet<String> autowiredBeanNames = new LinkedHashSet<>(1);\n\t\tTypeConverter typeConverter = beanFactory.getTypeConverter();\n\t\ttry {\n\t\t\tAssert.isInstanceOf(AutowireCapableBeanFactory.class, beanFactory);\n\t\t\tObject value = ((AutowireCapableBeanFactory) beanFactory).resolveDependency(\n\t\t\t\t\tdescriptor, beanName, autowiredBeanNames, typeConverter);\n\t\t\tregisterDependentBeans(beanFactory, beanName, autowiredBeanNames);\n\t\t\treturn value;\n\t\t}\n\t\tcatch (BeansException ex) {\n\t\t\tthrow new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);\n\t\t}\n\t}\n\n\tprivate Field getField(RegisteredBean registeredBean) {\n\t\tField field = ReflectionUtils.findField(registeredBean.getBeanClass(), this.fieldName);\n\t\tAssert.notNull(field, () -> \"No field '\" + this.fieldName + \"' found on \" +\n\t\t\t\tregisteredBean.getBeanClass().getName());\n\t\treturn field;\n\t}\n\n}\n","sourceCodeStart":170,"sourceCodeEnd":200,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredFieldValueResolver.java#L170-L200","documentation":"Thrown as an UnsatisfiedDependencyException when the BeanFactory cannot resolve a value for an @Autowired/@Value field at runtime in an AOT-processed application. The AOT-generated AutowiredFieldValueResolver calls resolveDependency for the field; if that lookup fails (missing bean, ambiguous type, conversion error) the underlying BeansException is wrapped with the InjectionPoint so you can see which field is broken. It is the AOT equivalent of the reflection-based AutowiredAnnotationBeanPostProcessor failure.","triggerScenarios":"Calling resolveAndSet(registeredBean, instance) or resolveValue on an AutowiredFieldValueResolver built forField/forRequiredField when beanFactory.resolveDependency(descriptor, ...) throws a BeansException. This happens when the declared field type has no candidate bean, multiple unqualified candidates, or a value that cannot be converted to the field type.","commonSituations":"Forgetting to register a bean of the field's type in the AOT-optimized context; using @Value('${missing.prop}') without a PropertySourcesPlaceholderConfigurer; a qualifier that no bean satisfies; circular/missing bean after trimming the context for native image; renaming a bean without updating the @Qualifier on the field.","solutions":["Read the InjectionPoint in the stack trace to identify the exact field and its declaring bean, then verify a bean of that type (and qualifier) is registered.","If the dependency is optional, build the resolver with forField(name) instead of forRequiredField(name), or annotate the field with @Autowired(required=false).","Add an explicit bean name via .withShortcut(beanName) or a @Qualifier on the field when multiple candidates of the same type exist.","Ensure placeholder/value resolution is configured (e.g. PropertySourcesPlaceholderConfigurer) and that referenced properties exist in the environment.","Re-run with the JVM (non-AOT) build to reproduce the same UnsatisfiedDependencyException for a friendlier, full-context stack trace."],"exampleFix":"// before: required field with no qualifying bean\n@AutowiredFieldValueResolver.forRequiredField(\"dataSource\")\n    .resolveAndSet(registeredBean, instance);\n\n// after: optional injection that tolerates absence\nAutowiredFieldValueResolver.forField(\"dataSource\")\n    .resolveAndSet(registeredBean, instance);","handlingStrategy":"try-catch","validationCode":"// Before resolving, confirm the candidate exists and is unique\nConfigurableListableBeanFactory bf = registeredBean.getBeanFactory();\nString[] names = bf.getBeanNamesForType(field.getType());\nif (names.length == 0 && required) {\n    throw new IllegalStateException(\"No bean of type \" + field.getType() + \" for field \" + field);\n}","typeGuard":null,"tryCatchPattern":"try {\n    resolver.resolveAndSet(registeredBean, instance);\n} catch (UnsatisfiedDependencyException ex) {\n    InjectionPoint ip = ex.getInjectionPoint();\n    // log ip, fall back to a default, or rethrow as a domain-specific error\n    throw new ConfigurationException(\"Cannot wire field \" + (ip != null ? ip.getField() : \"?\"), ex);\n}","preventionTips":["Run an ApplicationContext integration test that asserts all @Autowired fields resolve in the AOT context.","Prefer constructor injection over field injection so missing dependencies fail fast at startup.","Use @Qualifier on field injection points whenever multiple candidates of the type exist.","Keep the native-image subset (Spring AOT) in sync with bean registrations when trimming the context."],"tags":["spring","aot","dependency-injection","autowiring"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}