spring-projects/spring-framework · error · IllegalStateException
No StringValueResolver specified - pass a resolver object in
Error message
No StringValueResolver specified - pass a resolver object into the constructor or override the 'resolveStringValue' method
What it means
BeanDefinitionVisitor.resolveStringValue delegates placeholder resolution to a StringValueResolver supplied at construction. If no resolver was provided (the field is null) and the subclass did not override resolveStringValue, visiting a bean definition that contains String values (placeholders like ${...}) fails immediately with this IllegalStateException.
Source
Thrown at spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionVisitor.java:288
Object val = entry.getValue();
Object newVal = resolveValue(val);
newContent.put(newKey, newVal);
entriesModified = entriesModified || (newVal != val || newKey != key || newKeyHash != keyHash);
}
if (entriesModified) {
mapVal.clear();
mapVal.putAll(newContent);
}
}
/**
* Resolve the given String value, for example parsing placeholders.
* @param strVal the original String value
* @return the resolved String value
*/
protected @Nullable String resolveStringValue(String strVal) {
if (this.valueResolver == null) {
throw new IllegalStateException("No StringValueResolver specified - pass a resolver " +
"object into the constructor or override the 'resolveStringValue' method");
}
String resolvedValue = this.valueResolver.resolveStringValue(strVal);
// Return original String if not modified.
return (strVal.equals(resolvedValue) ? strVal : resolvedValue);
}
}
View on GitHub (pinned to e8729d0438)
Solutions
- Pass a StringValueResolver (e.g. from environment::resolveRequiredPlaceholders) into the BeanDefinitionVisitor constructor.
- Override resolveStringValue in your subclass to implement resolution directly.
- Prefer PropertySourcesPlaceholderConfigurer / ConfigurableEnvironment.resolvePlaceholders for normal placeholder resolution instead of using the visitor directly.
Example fix
// before BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(null); visitor.visitBeanDefinition(beanDef); // after StringValueResolver r = str -> env.resolveRequiredPlaceholders(str); BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(r); visitor.visitBeanDefinition(beanDef);
Defensive patterns
Strategy: validation
Validate before calling
if (visitorResolver == null && placeholderPresent(beanDefinition)) {
throw new IllegalStateException("BeanDefinitionVisitor needs a StringValueResolver to resolve placeholders");
} Type guard
boolean resolverAvailable(@Nullable StringValueResolver r) {
return r != null;
} Prevention
- Always pass a StringValueResolver to BeanDefinitionVisitor, or override resolveStringValue.
- Prefer PropertySourcesPlaceholderConfigurer / environment.resolvePlaceholders for placeholder resolution.
- Add a constructor assertion that the resolver is non-null when placeholders are expected.
When it happens
Trigger: Constructing a BeanDefinitionVisitor without a StringValueResolver and then visiting values that need resolving; or a subclass that calls super.resolveStringValue without supplying a resolver.
Common situations: Programmatic use of BeanDefinitionVisitor (e.g. PropertyPlaceholderConfigurer-like processing) without passing PropertyResolver.strValResolver; misusing the visitor standalone instead of through PropertySourcesPlaceholderConfigurer; custom visitor subclass forgetting to inject a resolver.
Related errors
- Lifecycle annotation requires a no-arg method: {}
- Value annotation must have a value attribute
- Cannot invoke instance method without factoryBeanName: {}
- Mapped value [{}] for scope key [{}] is not an instance of r
- Property 'serviceLocatorInterface' is required
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/d488ba36a53a9a7f.json.
Report an issue: GitHub.