{"id":"672ec98c7f6ec546","repo":"spring-projects/spring-framework","slug":"could-not-copy-property-targetpd-getname-fr","errorCode":null,"errorMessage":"Could not copy property '${targetPd.getName()}' from source to target","messagePattern":"Could not copy property '(.+?)' from source to target","errorType":"exception","errorClass":"FatalBeanException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/BeanUtils.java","lineNumber":831,"sourceCode":"\t\t\t\tCachedIntrospectionResults.forClass(source.getClass()) : null);\n\n\t\tfor (PropertyDescriptor targetPd : targetPds) {\n\t\t\tMethod writeMethod = targetPd.getWriteMethod();\n\t\t\tif (writeMethod != null && (ignoredProps == null || !ignoredProps.contains(targetPd.getName()))) {\n\t\t\t\tPropertyDescriptor sourcePd = (sourceResults != null ?\n\t\t\t\t\t\tsourceResults.getPropertyDescriptor(targetPd.getName()) : targetPd);\n\t\t\t\tif (sourcePd != null) {\n\t\t\t\t\tMethod readMethod = sourcePd.getReadMethod();\n\t\t\t\t\tif (readMethod != null) {\n\t\t\t\t\t\tif (isAssignable(writeMethod, readMethod, sourcePd, targetPd)) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tReflectionUtils.makeAccessible(readMethod);\n\t\t\t\t\t\t\t\tObject value = readMethod.invoke(source);\n\t\t\t\t\t\t\t\tReflectionUtils.makeAccessible(writeMethod);\n\t\t\t\t\t\t\t\twriteMethod.invoke(target, value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcatch (Throwable ex) {\n\t\t\t\t\t\t\t\tthrow new FatalBeanException(\n\t\t\t\t\t\t\t\t\t\t\"Could not copy property '\" + targetPd.getName() + \"' from source to target\", ex);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static boolean isAssignable(Method writeMethod, Method readMethod,\n\t\t\tPropertyDescriptor sourcePd, PropertyDescriptor targetPd) {\n\n\t\tType paramType = writeMethod.getGenericParameterTypes()[0];\n\t\tif (paramType instanceof Class<?> clazz) {\n\t\t\treturn ClassUtils.isAssignable(clazz, readMethod.getReturnType());\n\t\t}\n\t\telse if (paramType.equals(readMethod.getGenericReturnType())) {\n\t\t\treturn true;","sourceCodeStart":813,"sourceCodeEnd":849,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java#L813-L849","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nBeanUtils.copyProperties(source, target);\n// target.setSensitive(...) throws inside its setter -> FatalBeanException\n\n// after\nBeanUtils.copyProperties(source, target, \"sensitive\");\n// or handle the cause\ntry {\n    BeanUtils.copyProperties(source, target);\n} catch (FatalBeanException ex) {\n    log.error(\"copy failed on property; root cause:\", ex.getCause());\n}","handlingStrategy":"try-catch","validationCode":"// Validate getters/setters are invokable and types are compatible before copy\nPropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(target.getClass());\njava.util.Set<String> targetNames = new java.util.HashSet<>();\nfor (PropertyDescriptor pd : pds) {\n    if (pd.getReadMethod() != null && pd.getWriteMethod() != null) targetNames.add(pd.getName());\n}\n// Optionally dry-run read each getter on source to surface failures early\nfor (String name : targetNames) {\n    PropertyDescriptor spd = BeanUtils.getPropertyDescriptor(source.getClass(), name);\n    if (spd != null && spd.getReadMethod() != null) {\n        ReflectionUtils.makeAccessible(spd.getReadMethod());\n        ReflectionUtils.invokeMethod(spd.getReadMethod(), source); // throws if getter is bad\n    }\n}","typeGuard":"// Narrow to a known-safe source/target pair before copy\nstatic boolean isSafeCopyPair(Object src, Object target, String... ignore) {\n    try {\n        PropertyDescriptor[] tps = BeanUtils.getPropertyDescriptors(target.getClass());\n        java.util.Set<String> ign = ignore == null ? Set.of() : new java.util.HashSet<>(Arrays.asList(ignore));\n        for (PropertyDescriptor tp : tps) {\n            if (tp.getWriteMethod() == null || ign.contains(tp.getName())) continue;\n            PropertyDescriptor sp = BeanUtils.getPropertyDescriptor(src.getClass(), tp.getName());\n            if (sp == null || sp.getReadMethod() == null) continue;\n            if (!ClassUtils.isAssignable(tp.getWriteMethod().getParameterTypes()[0],\n                                         sp.getReadMethod().getReturnType())) return false;\n        }\n        return true;\n    } catch (Exception e) { return false; }\n}","tryCatchPattern":"try {\n    BeanUtils.copyProperties(source, target);\n} catch (FatalBeanException ex) {\n    // ex.getCause() holds the real reflection failure\n    log.warn(\"Skipping partial copy of {}\", ex.getMessage(), ex.getCause());\n}","preventionTips":["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."],"tags":["beanutils","copy-properties","reflection","spring-beans"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}