spring-projects/spring-framework · error · IllegalArgumentException

Specify 'targetObject' or 'targetBeanName' in combination…

Error message

Specify 'targetObject' or 'targetBeanName' in combination with 'propertyPath'

What it means

Thrown by PropertyPathFactoryBean.setBeanFactory() when a propertyPath has been supplied but neither targetObject nor targetBeanName was set. The property path needs a target to be evaluated against; without a target Spring cannot infer one (unlike the bean-name shorthand, propertyPath alone does not carry the bean name).

Solutions

  1. Add targetBeanName (e.g. <property name="targetBeanName" value="tb"/>) alongside propertyPath.
  2. Or add targetObject (an inner bean or ref) alongside propertyPath.
  3. If you wanted the bean-name shorthand, remove the propertyPath property and rely on the bean id 'tb.age'.

Example fix

<!-- before (broken) -->
<bean id="x" class="...PropertyPathFactoryBean">
  <property name="propertyPath" value="age"/>
</bean>
<!-- after -->
<bean id="x" class="...PropertyPathFactoryBean">
  <property name="targetBeanName" value="tb"/>
  <property name="propertyPath" value="age"/>
</bean>
Defensive patterns

Strategy: validation

Validate before calling

if (propertyPath != null && targetObject == null && targetBeanName == null) {
    throw new IllegalStateException("propertyPath requires a targetObject or targetBeanName");
}

Type guard

static boolean pathHasTarget(String propertyPath, String targetBeanName, Object targetObject) {
    return propertyPath == null || targetObject != null || targetBeanName != null;
}

Try / catch

try {
    fb.setBeanFactory(beanFactory);
} catch (IllegalArgumentException ex) {
    if (ex.getMessage().contains("in combination with 'propertyPath'")) {
        // add targetBeanName or targetObject, then retry
    }
    throw ex;
}

Prevention

When it happens

Trigger: XML with only <property name="propertyPath" value="age"/> and no target. Programmatic setPropertyPath("age") without setTargetObject/setTargetBeanName. Intent to use the bean-name shorthand but accidentally also setting propertyPath.

Common situations: Misunderstanding that the 'beanName.property' shorthand works only when NOTHING else is set; adding propertyPath disables the shorthand. Partial migration between the two forms.

Related errors


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

Appendix: source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/config/PropertyPathFactoryBean.java:169

	 */
	@Override
	public void setBeanName(String beanName) {
		this.beanName = StringUtils.trimAllWhitespace(BeanFactoryUtils.originalBeanName(beanName));
	}


	@Override
	public void setBeanFactory(BeanFactory beanFactory) {
		this.beanFactory = beanFactory;
		String targetBeanName = this.targetBeanName;

		if (this.targetBeanWrapper != null && targetBeanName != null) {
			throw new IllegalArgumentException("Specify either 'targetObject' or 'targetBeanName', not both");
		}

		if (this.targetBeanWrapper == null && targetBeanName == null) {
			if (this.propertyPath != null) {
				throw new IllegalArgumentException(
						"Specify 'targetObject' or 'targetBeanName' in combination with 'propertyPath'");
			}

			// No other properties specified: check bean name.
			int dotIndex;
			if (this.beanName == null || (dotIndex = this.beanName.indexOf('.')) <= 0) {
				throw new IllegalArgumentException(
						"Neither 'targetObject' nor 'targetBeanName' specified, and PropertyPathFactoryBean " +
						"bean name '" + this.beanName + "' does not follow 'beanName.property' syntax");
			}
			targetBeanName = this.beanName.substring(0, dotIndex);
			this.targetBeanName = targetBeanName;
			this.propertyPath = this.beanName.substring(dotIndex + 1);
		}

		else if (this.propertyPath == null) {
			// either targetObject or targetBeanName specified
			throw new IllegalArgumentException("'propertyPath' is required");

View on GitHub (pinned to 69bf83ad71)