{"record":{"id":"31f883517c9f8b98","repo":"spring-projects/spring-framework","slug":"cannot-create-default-implementation-for-interfa","errorCode":null,"errorMessage":"Cannot create default implementation for '{interfaceType.getName()}' mixin ({defaultImplType.getName()}): {ex}","messagePattern":"Cannot create default implementation for '(.+?)' mixin \\((.+?)\\): (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/support/DelegatePerTargetObjectIntroductionInterceptor.java","lineNumber":139,"sourceCode":"\tprivate Object getIntroductionDelegateFor(@Nullable Object targetObject) {\n\t\tsynchronized (this.delegateMap) {\n\t\t\tif (this.delegateMap.containsKey(targetObject)) {\n\t\t\t\treturn this.delegateMap.get(targetObject);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tObject delegate = createNewDelegate();\n\t\t\t\tthis.delegateMap.put(targetObject, delegate);\n\t\t\t\treturn delegate;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate Object createNewDelegate() {\n\t\ttry {\n\t\t\treturn ReflectionUtils.accessibleConstructor(this.defaultImplType).newInstance();\n\t\t}\n\t\tcatch (Throwable ex) {\n\t\t\tthrow new IllegalArgumentException(\"Cannot create default implementation for '\" +\n\t\t\t\t\tthis.interfaceType.getName() + \"' mixin (\" + this.defaultImplType.getName() + \"): \" + ex);\n\t\t}\n\t}\n\n}\n","sourceCodeStart":121,"sourceCodeEnd":145,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/support/DelegatePerTargetObjectIntroductionInterceptor.java#L121-L145","documentation":"Thrown by DelegatePerTargetObjectIntroductionInterceptor.createNewDelegate() (also invoked once in the constructor to fail fast) when ReflectionUtils.accessibleConstructor(defaultImplType).newInstance() blows up. The interceptor needs to instantiate the default-implementation class per target object, so any failure in constructing it is wrapped in an IllegalArgumentException naming both the interfaceType and the defaultImplType.","triggerScenarios":"new DelegatePerTargetObjectIntroductionInterceptor(defaultImplType, interfaceType) where defaultImplType has no no-arg constructor, is abstract, is an interface, is a non-static inner class, has a private constructor that reflection cannot open, or its constructor throws.","commonSituations":"Passing an interface or abstract class as the default impl; passing a class whose only constructor requires arguments; a default impl type whose no-arg constructor throws (e.g. requires config); security manager / module access rules blocking reflective instantiation.","solutions":["Ensure defaultImplType is a concrete public class with a public no-arg constructor.","If the delegate needs arguments, subclass DelegatePerTargetObjectIntroductionInterceptor and override getIntroductionDelegateFor / createNewDelegate to build it yourself.","Check the wrapped cause (ex) in the stack trace to identify the exact reflection failure and address that (add constructor, loosen visibility, fix module exports).","Verify defaultImplType actually implements interfaceType so the mixin is coherent."],"exampleFix":"// before\nnew DelegatePerTargetObjectIntroductionInterceptor(Lockable.class, Lockable.class); // Lockable is an interface\n\n// after\nnew DelegatePerTargetObjectIntroductionInterceptor(LockableImpl.class, Lockable.class);","handlingStrategy":"validation","validationCode":"Class<?> defaultImplType = ...;\nint mods = defaultImplType.getModifiers();\nif (defaultImplType.isInterface() || Modifier.isAbstract(mods)) {\n    throw new IllegalArgumentException(\"defaultImplType must be concrete: \" + defaultImplType);\n}\nif (Arrays.stream(defaultImplType.getConstructors()).noneMatch(c -> c.getParameterCount() == 0)) {\n    throw new IllegalArgumentException(\"defaultImplType needs a public no-arg constructor: \" + defaultImplType);\n}\nnew DelegatePerTargetObjectIntroductionInterceptor(defaultImplType, interfaceType);","typeGuard":"static boolean isInstantiableWithNoArg(Class<?> c) {\n    return !c.isInterface() && !Modifier.isAbstract(c.getModifiers())\n        && Arrays.stream(c.getConstructors()).anyMatch(ct -> ct.getParameterCount() == 0);\n}","tryCatchPattern":null,"preventionTips":["Always pass a concrete class with a public no-arg constructor as defaultImplType.","Add a constructor sanity test that calls new DelegatePerTargetObjectIntroductionInterceptor(impl, ifc) at startup.","Subclass and override createNewDelegate if your delegate genuinely needs arguments."],"tags":["spring-aop","introduction","reflection","instantiation"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}