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
- Read the attached cause (ex.getCause()) first - it is the real exception, not this wrapper.
- Exclude the failing property via the ignoreProperties varargs or an override of copyProperties that skips it.
- Ensure the getter/setter are public and that the source object is fully initialized before copying.
- If running under JPMS, add '--add-opens java.base/java.lang=ALL-UNNAMED' or open the relevant module to Spring.
- 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
- Always log getCause() - the wrapper hides the root exception.
- Pass an explicit ignoreProperties list for volatile fields (passwords, lazy fields).
- Prefer mapping via MapStruct over BeanUtils.copyProperties for non-trivial DTOs.
- Keep getters side-effect free and tolerant of uninitialized state.
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
- Illegal arguments for constructor
- Target class [${target.getClass().getName()}] not assignable
- Specified class is an interface
- Is it an abstract class?
- Is the constructor accessible?
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/672ec98c7f6ec546.json.
Report an issue: GitHub.