spring-projects/spring-framework · error · IllegalArgumentException
Target class [{target.getClass().getName()}] not assignable
Error message
Target class [{target.getClass().getName()}] not assignable to editable class [{editable.getName()}] What it means
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.
Source
Thrown at spring-beans/src/main/java/org/springframework/beans/BeanUtils.java:805
* when matching properties in the source and target objects. See the
* documentation for {@link #copyProperties(Object, Object)} for details.
* @param source the source bean
* @param target the target bean
* @param editable the class (or interface) to restrict property setting to
* @param ignoreProperties array of property names to ignore
* @throws BeansException if the copying failed
* @see BeanWrapper
*/
private static void copyProperties(Object source, Object target, @Nullable Class<?> editable,
String @Nullable ... ignoreProperties) throws BeansException {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Class<?> actualEditable = target.getClass();
if (editable != null) {
if (!editable.isInstance(target)) {
throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
"] not assignable to editable class [" + editable.getName() + "]");
}
actualEditable = editable;
}
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
Set<String> ignoredProps = (ignoreProperties != null ? new HashSet<>(Arrays.asList(ignoreProperties)) : null);
CachedIntrospectionResults sourceResults = (actualEditable != source.getClass() ?
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)) {View on GitHub (pinned to 69bf83ad71)
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.
Example fix
// before BeanUtils.copyProperties(src, target, SomeInterface.class); // target does not implement SomeInterface // after - restrict to a type target implements BeanUtils.copyProperties(src, target, TargetType.class); // or no restriction BeanUtils.copyProperties(src, target);
Defensive patterns
Strategy: validation
Validate before calling
// before calling the editable-restricted copyProperties
Class<?> editable = SomeInterface.class;
if (editable != null && !editable.isInstance(target)) {
throw new IllegalArgumentException(
"target is not a " + editable.getName());
}
BeanUtils.copyProperties(src, target, editable); Type guard
static boolean targetIsEditable(Object target, Class<?> editable) {
return editable == null || editable.isInstance(target);
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Could not copy property '{targetPd.getName()}' from source t
- Property referenced in indexed property path '{tokens.canoni
- Property referenced in indexed property path '{propertyName}
- Invalid property '{propertyName}' of bean class [{beanClass.
- Failed properties: {propertyAccessExceptions}
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/107d638f21b00fde.
Report an issue: GitHub.