spring-projects/spring-framework · error · BeanDefinitionStoreException

Error registering bean definition

Error message

Error registering bean definition

What it means

Wrapped as a BeanDefinitionStoreException (message prefix 'Error registering bean definition') inside PlaceholderConfigurerSupport.doProcessProperties() when BeanDefinitionVisitor.visitBeanDefinition(bean) throws while a placeholder configurer processes each bean definition. The underlying cause's message is appended, so the real problem is usually an unresolvable ${placeholder} or a type-resolution error during placeholder substitution. This is the umbrella error thrown by PropertyPlaceholderConfigurer / PropertySourcesPlaceholderConfigurer when applying replacements fails for a given bean.

Solutions

  1. Read the wrapped cause message to find the exact placeholder key that failed, then add that key to your properties file or Environment.
  2. Register/enable a PropertySourcesPlaceholderConfigurer (or context:property-placeholder) pointed at the correct locations and ensure those files resolve on the classpath.
  3. If the placeholder is optional, set ignoreUnresolvablePlaceholders=true or give an inline default: value="${some.key:defaultValue}".
  4. Verify active profiles / environment so the right PropertySource is loaded before bean definitions are post-processed.

Example fix

<!-- before (broken): key not found -->
<property name="url" value="jdbc:${jdbc.dbname}"/>
<!-- after: add inline default -->
<property name="url" value="jdbc:${jdbc.dbname:defaultdb}"/>
Defensive patterns

Strategy: try-catch

Validate before calling

// Before refresh, verify all ${...} placeholders resolve against the Environment
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
for (String name : beanFactory.getBeanDefinitionNames()) {
    BeanDefinition bd = beanFactory.getBeanDefinition(name);
    // scan resolved values / placeholders via a PropertyResolver dry-run if available
}

Type guard

// No type guard; this is a runtime resolution failure. Validate keys exist instead.
static boolean placeholderResolves(Environment env, String key) {
    return env.containsProperty(key);
}

Try / catch

try {
    context.refresh();
} catch (BeanDefinitionStoreException ex) {
    Throwable cause = ex.getMostSpecificCause();
    if (cause instanceof IllegalArgumentException iae && iae.getMessage().contains("placeholder")) {
        // extract the unresolved key and add it, then retry refresh
    }
    throw ex;
}

Prevention

When it happens

Trigger: A bean definition value containing ${some.key} where 'some.key' is missing from every property source and ignoreUnresolvablePlaceholders is false (the default). Placeholders in bean names, aliases, or property values that the visitor cannot resolve. A nested BeansException (e.g. type conversion after substitution) during the visit.

Common situations: Properties file missing or not on the classpath, so the placeholder source is empty. Typo in the placeholder key vs. the properties key. Profile-specific properties not activated. Using ${...} in a value but only registering the PropertySourcesPlaceholderConfigurer conditionally. Circular or recursive placeholder references.

Related errors


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

Appendix: source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/config/PlaceholderConfigurerSupport.java:253

		this.beanFactory = beanFactory;
	}

	protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
			StringValueResolver valueResolver) {

		BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);

		String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
		for (String curName : beanNames) {
			// Check that we're not parsing our own bean definition,
			// to avoid failing on unresolvable placeholders in properties file locations.
			if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
				BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
				try {
					visitor.visitBeanDefinition(bd);
				}
				catch (Exception ex) {
					throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex);
				}
			}
		}

		// Resolve placeholders in alias target names and aliases as well.
		beanFactoryToProcess.resolveAliases(valueResolver);

		// Resolve placeholders in embedded values such as annotation attributes.
		beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
	}

}

View on GitHub (pinned to 69bf83ad71)