{"record":{"id":"107d638f21b00fde","repo":"spring-projects/spring-framework","slug":"target-class-target-getclass-getname-not-a","errorCode":null,"errorMessage":"Target class [{target.getClass().getName()}] not assignable to editable class [{editable.getName()}]","messagePattern":"Target class \\[(.+?)\\] not assignable to editable class \\[(.+?)\\]","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/BeanUtils.java","lineNumber":805,"sourceCode":"\t * when matching properties in the source and target objects. See the\n\t * documentation for {@link #copyProperties(Object, Object)} for details.\n\t * @param source the source bean\n\t * @param target the target bean\n\t * @param editable the class (or interface) to restrict property setting to\n\t * @param ignoreProperties array of property names to ignore\n\t * @throws BeansException if the copying failed\n\t * @see BeanWrapper\n\t */\n\tprivate static void copyProperties(Object source, Object target, @Nullable Class<?> editable,\n\t\t\tString @Nullable ... ignoreProperties) throws BeansException {\n\n\t\tAssert.notNull(source, \"Source must not be null\");\n\t\tAssert.notNull(target, \"Target must not be null\");\n\n\t\tClass<?> actualEditable = target.getClass();\n\t\tif (editable != null) {\n\t\t\tif (!editable.isInstance(target)) {\n\t\t\t\tthrow new IllegalArgumentException(\"Target class [\" + target.getClass().getName() +\n\t\t\t\t\t\t\"] not assignable to editable class [\" + editable.getName() + \"]\");\n\t\t\t}\n\t\t\tactualEditable = editable;\n\t\t}\n\t\tPropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);\n\t\tSet<String> ignoredProps = (ignoreProperties != null ? new HashSet<>(Arrays.asList(ignoreProperties)) : null);\n\t\tCachedIntrospectionResults sourceResults = (actualEditable != source.getClass() ?\n\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)) {","sourceCodeStart":787,"sourceCodeEnd":823,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java#L787-L823","documentation":"Thrown by BeanUtils.copyProperties(source, target, editable, ignoreProperties) when an 'editable' restriction class/interface is supplied but the target object is not an instance of it. Spring uses the editable class to decide which properties to copy, so it first validates that target is assignable to editable. This is a programming-contract IllegalArgumentException (not a BeansException) thrown before any copying happens.","triggerScenarios":"Calling BeanUtils.copyProperties(Object source, Object target, Class<?> editable) (or the variant with ignoreProperties) where editable is a class/interface that target does not implement or extend. For example passing editable = SomeInterface.class while target is a concrete class that does not implement SomeInterface.","commonSituations":"Passing the wrong class literal as the editable argument (e.g. passing the source's class instead of an interface the target implements), copy-pasting a copyProperties call and forgetting to update the class, or refactoring a target bean to no longer implement an interface while copyProperties calls still reference it.","solutions":["Make the target object's class implement/extend the class passed as 'editable', or pass an interface the target already implements.","Pass null as editable to copy from all properties of the target's actual class instead of restricting to an editable type.","Pass editable = target.getClass() (or a superclass/interface of it) so isInstance(target) holds."],"exampleFix":"// before\nBeanUtils.copyProperties(src, target, SomeInterface.class);\n// target does not implement SomeInterface\n\n// after - restrict to a type target implements\nBeanUtils.copyProperties(src, target, TargetType.class);\n// or no restriction\nBeanUtils.copyProperties(src, target);","handlingStrategy":"validation","validationCode":"// before calling the editable-restricted copyProperties\nClass<?> editable = SomeInterface.class;\nif (editable != null && !editable.isInstance(target)) {\n    throw new IllegalArgumentException(\n        \"target is not a \" + editable.getName());\n}\nBeanUtils.copyProperties(src, target, editable);","typeGuard":"static boolean targetIsEditable(Object target, Class<?> editable) {\n    return editable == null || editable.isInstance(target);\n}","tryCatchPattern":null,"preventionTips":["Always derive 'editable' from interfaces the target is known to implement.","Prefer the no-editable overload unless you specifically need property restriction.","Add a unit test asserting copyProperties callers pass an interface implemented by the target type."],"tags":["bean-utils","copy-properties","type-mismatch","spring-beans"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}