spring-projects/spring-framework · error · IllegalStateException

No StringValueResolver specified - pass a resolver object…

Error message

No StringValueResolver specified - pass a resolver object into the constructor or override the 'resolveStringValue' method

What it means

Thrown as an IllegalStateException when BeanDefinitionVisitor.resolveStringValue is called but no StringValueResolver has been provided. The visitor (used to resolve placeholders in bean definition property/constructor values) requires a resolver; if it was constructed without one and the subclass did not override resolveStringValue, attempting to resolve any string value fails.

Solutions

  1. Pass a resolver to the visitor: new BeanDefinitionResolver(embeddedValueResolver) or new BeanDefinitionVisitor(beanFactory) where beanFactory is a ConfigurableBeanFactory.
  2. If subclassing, override resolveStringValue(String) to implement your own resolution so the null-resolver path is never hit.
  3. Register a PropertySourcesPlaceholderConfigurer / PropertyResolver in the context so an EmbeddedValueResolver is available.
  4. Avoid visiting bean definitions that contain unresolved placeholders, or strip them before visiting.

Example fix

// before: no resolver -> IllegalStateException on first placeholder
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor();
visitor.visitBeanDefinition(beanDefinition);

// after: pass a resolver derived from the bean factory
StringValueResolver resolver = new EmbeddedValueResolver(beanFactory);
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(resolver);
visitor.visitBeanDefinition(beanDefinition);
Defensive patterns

Strategy: validation

Validate before calling

StringValueResolver resolver = new EmbeddedValueResolver(beanFactory);
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(resolver);
Assert.notNull(resolver, "StringValueResolver must be set before visiting");

Prevention

When it happens

Trigger: Constructing a BeanDefinitionVisitor() with the no-arg constructor (resolver stays null) and then calling visitBeanDefinition / resolveStringValue on a bean definition that contains placeholder strings. The default resolveStringValue accesses this.valueResolver, which is null, so it throws.

Common situations: Using BeanDefinitionVisitor to walk a bean definition manually without passing an EmbeddedValueResolver or ConfigurableBeanFactory; PropertySourcesPlaceholderConfigurer not registered so no resolver is in scope when the visitor runs; subclass of BeanDefinitionVisitor that forgot to override resolveStringValue; programmatic bean definition processing that expects placeholders but supplies no resolver.

Related errors


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

Appendix: 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 69bf83ad71)