spring-projects/spring-framework · error · FatalBeanException

Could not copy property '${targetPd.getName()}' from source

Error message

Could not copy property '${targetPd.getName()}' from source to target

What it means

Thrown by BeanUtils.copyProperties (FatalBeanException) when invoking a property's read or write method via reflection fails for any reason. The message names the property being copied; the original Throwable (InvocationTargetException wrapping an application exception, or an IllegalAccessException) is attached as the cause. It signals that bean-to-bean copying aborted mid-property, not that the property was missing.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/BeanUtils.java:831

				CachedIntrospectionResults.forClass(source.getClass()) : null);

		for (PropertyDescriptor targetPd : targetPds) {
			Method writeMethod = targetPd.getWriteMethod();
			if (writeMethod != null && (ignoredProps == null || !ignoredProps.contains(targetPd.getName()))) {
				PropertyDescriptor sourcePd = (sourceResults != null ?
						sourceResults.getPropertyDescriptor(targetPd.getName()) : targetPd);
				if (sourcePd != null) {
					Method readMethod = sourcePd.getReadMethod();
					if (readMethod != null) {
						if (isAssignable(writeMethod, readMethod, sourcePd, targetPd)) {
							try {
								ReflectionUtils.makeAccessible(readMethod);
								Object value = readMethod.invoke(source);
								ReflectionUtils.makeAccessible(writeMethod);
								writeMethod.invoke(target, value);
							}
							catch (Throwable ex) {
								throw new FatalBeanException(
										"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
							}
						}
					}
				}
			}
		}
	}

	private static boolean isAssignable(Method writeMethod, Method readMethod,
			PropertyDescriptor sourcePd, PropertyDescriptor targetPd) {

		Type paramType = writeMethod.getGenericParameterTypes()[0];
		if (paramType instanceof Class<?> clazz) {
			return ClassUtils.isAssignable(clazz, readMethod.getReturnType());
		}
		else if (paramType.equals(readMethod.getGenericReturnType())) {
			return true;

View on GitHub (pinned to e8729d0438)

Solutions

  1. Read the attached cause (ex.getCause()) first - it is the real exception, not this wrapper.
  2. Exclude the failing property via the ignoreProperties varargs or an override of copyProperties that skips it.
  3. Ensure the getter/setter are public and that the source object is fully initialized before copying.
  4. If running under JPMS, add '--add-opens java.base/java.lang=ALL-UNNAMED' or open the relevant module to Spring.
  5. Replace the failing getter/setter with field access via DirectFieldAccessor if the accessor logic itself is the problem.

Example fix

// before
BeanUtils.copyProperties(source, target);
// target.setSensitive(...) throws inside its setter -> FatalBeanException

// after
BeanUtils.copyProperties(source, target, "sensitive");
// or handle the cause
try {
    BeanUtils.copyProperties(source, target);
} catch (FatalBeanException ex) {
    log.error("copy failed on property; root cause:", ex.getCause());
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate getters/setters are invokable and types are compatible before copy
PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(target.getClass());
java.util.Set<String> targetNames = new java.util.HashSet<>();
for (PropertyDescriptor pd : pds) {
    if (pd.getReadMethod() != null && pd.getWriteMethod() != null) targetNames.add(pd.getName());
}
// Optionally dry-run read each getter on source to surface failures early
for (String name : targetNames) {
    PropertyDescriptor spd = BeanUtils.getPropertyDescriptor(source.getClass(), name);
    if (spd != null && spd.getReadMethod() != null) {
        ReflectionUtils.makeAccessible(spd.getReadMethod());
        ReflectionUtils.invokeMethod(spd.getReadMethod(), source); // throws if getter is bad
    }
}

Type guard

// Narrow to a known-safe source/target pair before copy
static boolean isSafeCopyPair(Object src, Object target, String... ignore) {
    try {
        PropertyDescriptor[] tps = BeanUtils.getPropertyDescriptors(target.getClass());
        java.util.Set<String> ign = ignore == null ? Set.of() : new java.util.HashSet<>(Arrays.asList(ignore));
        for (PropertyDescriptor tp : tps) {
            if (tp.getWriteMethod() == null || ign.contains(tp.getName())) continue;
            PropertyDescriptor sp = BeanUtils.getPropertyDescriptor(src.getClass(), tp.getName());
            if (sp == null || sp.getReadMethod() == null) continue;
            if (!ClassUtils.isAssignable(tp.getWriteMethod().getParameterTypes()[0],
                                         sp.getReadMethod().getReturnType())) return false;
        }
        return true;
    } catch (Exception e) { return false; }
}

Try / catch

try {
    BeanUtils.copyProperties(source, target);
} catch (FatalBeanException ex) {
    // ex.getCause() holds the real reflection failure
    log.warn("Skipping partial copy of {}", ex.getMessage(), ex.getCause());
}

Prevention

When it happens

Trigger: Calling BeanUtils.copyProperties(source, target) or copyProperties(source, target, editable, ignoreProperties) where a shared property's getter throws (e.g. lazy init, NPE inside getter), the getter/setter is non-public and the security manager / module access denies ReflectionUtils.makeAccessible, or the read value's runtime type is assignable but the setter rejects it at invocation.

Common situations: Copying onto a proxy (Hibernate/CGLIB) whose setter throws; source getter dereferences a null uninitialized field; running under a strict JVM module (JPMS, --illegal-access=deny) where makeAccessible is rejected; copying beans whose getter performs validation that fails on partial data.

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/672ec98c7f6ec546.json. Report an issue: GitHub.