spring-projects/spring-framework · error · IllegalArgumentException

'propertyPath' is required

Error message

'propertyPath' is required

What it means

Thrown by PropertyPathFactoryBean.setBeanFactory() when a target (targetObject or targetBeanName) has been configured but propertyPath was not. After binding a target, Spring needs the path to evaluate; the bean-name shorthand cannot apply because a target is already present (the shorthand only kicks in when nothing is set).

Solutions

  1. Add <property name="propertyPath" value="age"/> (or setPropertyPath("age")) alongside the target.
  2. Use a nested path if needed, e.g. value="spouse.age".
  3. If you intended the shorthand, remove the targetBeanName/targetObject and rename the bean to 'tb.age'.

Example fix

// before (broken)
PropertyPathFactoryBean fb = new PropertyPathFactoryBean();
fb.setTargetBeanName("tb");
// after
PropertyPathFactoryBean fb = new PropertyPathFactoryBean();
fb.setTargetBeanName("tb");
fb.setPropertyPath("age");
Defensive patterns

Strategy: validation

Validate before calling

if ((targetObject != null || targetBeanName != null) && propertyPath == null) {
    throw new IllegalStateException("propertyPath is required when a target is set");
}

Type guard

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

Try / catch

try {
    fb.setBeanFactory(beanFactory);
} catch (IllegalArgumentException ex) {
    if (ex.getMessage().contains("'propertyPath' is required")) {
        fb.setPropertyPath("age");
    }
    throw ex;
}

Prevention

When it happens

Trigger: XML with <property name="targetBeanName" value="tb"/> but no <property name="propertyPath"/>. Programmatic setTargetBeanName("tb") without setPropertyPath. Same for setTargetObject without a path.

Common situations: Setting the target then forgetting the path. Refactoring that dropped the propertyPath element while keeping the target.

Related errors


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

Appendix: source

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

				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");
		}

		if (this.targetBeanWrapper == null && StringUtils.hasLength(targetBeanName) &&
				this.beanFactory.isSingleton(targetBeanName)) {
			// Eagerly fetch singleton target bean, and determine result type.
			Object bean = this.beanFactory.getBean(targetBeanName);
			this.targetBeanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(bean);
			this.resultType = this.targetBeanWrapper.getPropertyType(this.propertyPath);
		}
	}


	@Override
	public @Nullable Object getObject() throws BeansException {
		BeanWrapper target = this.targetBeanWrapper;
		if (target != null) {
			if (logger.isWarnEnabled() && this.targetBeanName != null &&
					this.beanFactory instanceof ConfigurableBeanFactory cbf &&

View on GitHub (pinned to 69bf83ad71)